




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第6章類的繼承C++高級程序設計
第6章類的繼承
繼承(Inheritance)是C++語言的重要機制,是面向對象程序設計方法的三個基本特征之一。繼承允許程序在已有類的基礎上進行擴展,是一種重要的代碼復用手段。繼承反映了類與類之間的一種層次關系,更是現實世界中事物之間存在的復雜聯(lián)系的體現。繼承也體現了人類認識事物由簡單到復雜的過程和思考問題的方法。本章著重學習繼承這一面向對象程序設計的重要概念,以及在C++語言中實現繼承的相關技術。6.1面向對象編程——繼承:概念與思想
6.2
派生類:定義及相關技術
6.3派生類的構造與析構6.4多重繼承與虛基類
6.5
案例實訓
第6章類的繼承6.1面向對象編程——繼承:概念與思想類的繼承機制是指類可以在已定義類的基礎上派生出新類,新類將擁有原有類的數據和函數,并且可以增添新的數據和函數成員,或者對原有類中的成員進行更新。
在面向對象編程中,原有類被稱為基類(BaseClass)或父類(SuperClass),新產生的類被稱為派生類(DerivedClass)或子類(SubClass)。
例如,由學生類可以派生出中學生類、大學生類和研究生類。由交通工具類可派生出汽車類、輪船類和飛機類,而汽車類又可充當客車類和卡車類的基類。
類的繼承有兩種方式:單繼承和多重繼承。單繼承的派生類有且僅有一個直接基類,如圖6-1中的飛機類是單繼承于交通工具類,戰(zhàn)斗機類則是單繼承于飛機類。在單繼承中,可以視派生類是基類的特例。多重繼承的派生類具有兩個或兩個以上的直接基類,如圖6-1中的水陸兩用車類繼承于客車類和客船類。在多重繼承中,派生類是從多個基類派生而來,是一個具有多個基類特征的復合體,就像雜交水稻具有不同稻種特性一樣。6.1面向對象編程——繼承:概念與思想6.1面向對象編程——繼承:概念與思想圖6-1類的單繼承和多重繼承6.1面向對象編程——繼承:概念與思想繼承與組合都屬于面向對象的代碼復用技術。繼承和組合既有區(qū)別,也有聯(lián)系。在一些復雜的類的設計中,二者經常是一起使用。在某些情況下,繼承和組合的實現方法還可以互換。例如,圓(Circle)類的設計,其圓心用點(Point)類來描述,此時,即可以以Point類為父類設計Circle類,使其擁有圓心坐標,也可以在Circle類中用Point類定義數據成員center。代碼框架如下:classPoint{//點類private: doublex,y;public:...};classCircle{//組合 private: Pointcenter; doubleradius; public: ...}; classCircle:publicPoint{//繼承private: doubleradius;public:...};6.1面向對象編程——繼承:概念與思想6.2派生類
:定義及相關技術派生類繼承了基類的數據成員和函數成員。C++支持3種繼承方式,不同的繼承方式決定了基類中成員被派生類繼承后的可見性。派生類中可以重定義基類中的同名成員函數。派生類與基類屬于同一類族,它們之間存在賦值兼容問題。本節(jié)主要介紹派生類的定義、繼承方式、成員函數覆蓋和賦值兼容等基礎知識。6.2派生類:定義及相關技術6.2.1派生類的定義定義派生類的一般格式如下:class<派生類名>:[<繼承方式1>]<基類名1>,...,[<繼承方式n>][<基類名n>]{<派生類的成員>};其中:與類的定義相似,用關鍵字class標明是類定義。區(qū)別在于派生類名后(用冒號分隔)列出所繼承的基類。對于單繼承只有一個基類,而多重繼承則有多個基類,它們之間用逗號分隔。繼承方式有3種:公有繼承(public)、私有繼承(private)和保護繼承(protected)。不指明繼承方式等同于私有繼承。派生類中的成員包括數據成員和成員函數。與普通類相同,派生類中數據成員的訪問控制限定通常是私有的,成員函數是公有的。6.2派生類:定義及相關技術【例6-1】派生類定義與派生類對象中的數據成員和成員函數。
運行結果:baseObj:baseData=100derivedObj:baseData=500derivedData=600
6.2派生類:定義及相關技術跟蹤與觀察:(1) 從前面的知識可知,對象在邏輯上數據成員與函數成員具有封裝性,但在物理上其實是存儲在內存的不同區(qū)域(堆棧區(qū)和代碼區(qū))。從圖6-2(a)可見,派生類對象derivedObj的數據部分含有兩部分數據BaseClass和derivedData(其值為600),展開BaseClass項,其中含有baseData(其值為500)。對象derivedObj自動包含了基類部分,并且派生類的構造函數通過調用基類的構造函數將500賦給了baseData。(2) 從圖6-2(b)可見,派生類對象derivedObj繼承了基類的公有函數show,DerivedClass::show的值是0x010a14b0,BaseClass::show(void)與BaseClass::show完全相同。
6.2派生類:定義及相關技術(b)圖6-2派生類對象擁有的數據成員和成員函數派生類繼承基類的成員函數也是自動的,系統(tǒng)自動將基類的成員函數show當成派生類的成員函數show,但實際上兩者都是同一個函數voidBaseClass::show(void)。6.2派生類:定義及相關技術C++中下列特殊的成員函數不被派生類所繼承: ①構造函數; ②析構函數; ③私有函數; ④賦值運算符(=)重載函數。構造函數、析構函數和賦值運算符重載函數不被繼承的主要原因是基類的對應函數不能處理在派生類引入的新的數據成員,不能完全正確地完成相應的功能(只能正確地處理基類的數據成員)。因而,派生類對象在調用這些函數時會首先調用基類的對應函數。6.2派生類:定義及相關技術在派生類設計時,需要注意下面幾點:派生類吸收基類成員。派生類繼承吸收了基類的全部數據成員以及除了構造函數、析構函數、賦值和私有函數之外的全部函數成員。派生類修改基類成員。對繼承到派生類中基類成員的修改包括兩個方面:一是基類成員的訪問方式問題,這由派生類定義時的繼承方式來控制;二是對基類成員的覆蓋,也就是在派生類中定義了與基類中同名的數據成員或成員函數,由于作用域不同,于是發(fā)生同名覆蓋(Override),基類中的成員就被替換成派生類中的同名成員。派生類增添新成員。在派生類中,除了從基類中繼承過來的成員外,還可以根據需要在派生類中添加新的數據成員和成員函數,以此實現必要的新功能。在派生類中添加新成員是繼承和派生機制的核心,它保證了派生類是基類的擴展。6.2派生類:定義及相關技術6.2.2繼承方式與訪問控制在類的定義中,用訪問控制符private、protected和public說明成員的可見性。公有成員能被任何函數所訪問,而私有和保護成員僅能接受類的成員函數和類的友元(包括友元函數和友元類)的訪問。派生類繼承于基類,那么基類成員對派生類函數的可見性如何呢?派生類在定義時需要指定繼承方式,所使用的關鍵字也是private、protected和public,它們分別對應私有繼承、保護繼承和公有繼承3種方式。不同的繼承方式決定了基類中的成員在派生類中的可見性,表6-1列出了3種繼承方式在派生類中影響基類成員的可見性和訪問控制屬性的情況。6.2派生類:定義及相關技術表6-1派生類對基類成員的訪問能力
基類成員繼承方式privateprotectedpublicprivate不可訪問可訪問/私有成員可訪問/私有成員protected不可訪問可訪問/保護成員可訪問/保護成員public不可訪問可訪問/保護成員可訪問/公有成員6.2派生類:定義及相關技術表6-1中的“不可訪問”和“可訪問”表示在派生類中訪問基類成員的能力?!八接谐蓡T”、“保護成員”和“公有成員”表示基類成員在派生類中訪問控制屬性變化情況。例如,基類是public的成員采用private繼承方式時,表中相應項為“可訪問/私有成員”,表示在派生類中可直接訪問基類的公有成員,但該成員在派生類中其訪問控制屬性已被改為是私有成員,因此從派生類對象外不可直接訪問基類的公有成員(從基類對象外可以直接訪問)。派生類中基類成員訪問控制屬性的改變直接影響到基類成員在派生類對象外的訪問能力。6.2派生類:定義及相關技術從縱向觀察表6-1可知:基類的私有成員無論采用怎樣的繼承方式,它在派生類中均不可訪問,也不存在訪問控制屬性改變的問題?;愔械乃接谐蓡T只能通過保護或公有的函數訪問。基類的保護成員在派生類中所有的繼承方式均可直接訪問,不過私有繼承方式會把基類訪問控制屬性是保護成員的轉換為派生類中的私有成員,而保護和公有繼承方式依然保持其為保護成員的訪問控制屬性?;惖墓谐蓡T在派生類中也是可直接訪問的,派生類中基類成員的訪問控制屬性均隨繼承方式而改變。從橫向觀察表6-1可知,3種繼承方式都不改變從派生類訪問基類成員的能力,但私有和保護繼承方式均會改變基類成員在派生類中的訪問控制屬性,而只有公有繼承方式保持基類成員的訪問控制屬性在派生類中不變。在應用中,公有繼承方式絕對是主流的派生方式,其他兩種方式使用較少。6.2派生類:定義及相關技術如果對private、protected、public這3個關鍵字的訪問控制能力按從高到低的順序排序,則private最高,protected次之,而public最低。派生類中,基類成員的訪問控制屬性改變與否其實遵守如下準則:“強者優(yōu)先”,即由基類成員在基類中的訪問控制符和派生類在繼承基類時所使用的繼承方式符(兩者中的“強者”)決定其在派生類中的訪問控制屬性?!纠?-2】3種繼承方式對訪問控制能力的影響示例。
6.2派生類:定義及相關技術程序說明:程序中定義了Base基類,其中含有私有的數據privateData和函數privateFunction,受保護的數據protectedData和函數protectedFunction,公有的數據publicData和函數publicFunction、show和構造函數。在此基礎上,分別用3種繼承方式定義了派生類privateDerived、protedtedDerived和publicDerived。3個派生類的結構十分相似,除構造函數外,callBaseFunction函數調用Base類的4個成員函數。privateFunction在3個派生類中均不能被調用,而其他函數都可以。在程序的主函數中,定義了3個派生類的對象,并試圖通過這些對象調用基類的4個成員函數(privateFunction、protectedFunction、publicFunction和show),但僅有公有派生對象publicDerivedObj能調用公有函數publicFunction和show。
6.2派生類:定義及相關技術6.2.3成員函數的同名覆蓋與隱藏改造基類成員函數是派生類在基類上擴展功能的重要手段之一。在派生類中重新定義基類的同名成員函數后,基類中的同名成員函數將被同名覆蓋(Override)或隱藏(Hide)。派生類中重定義的同名成員函數的函數簽名決定了基類中的成員函數是被同名覆蓋還是被隱藏。同名覆蓋是由于派生類與基類的同名成員函數的函數簽名相同,派生類對象在調用同名成員函數時,系統(tǒng)調用派生類的同名成員函數,而基類的相應函數被遮蓋。隱藏是由于派生類與基類的同名成員函數的函數簽名不同(即函數名相同而形參不同),派生類對象在調用同名成員函數時,系統(tǒng)只在派生類中查找,不再深入到基類。派生類的同名成員函數阻止了對基類中同名函數的訪問。6.2派生類:定義及相關技術編譯器調用類的成員函數的方法是:根據函數名(不是函數簽名)沿著類的繼承鏈逐級向上查找相匹配的函數定義。如果在類層次結構的某個類中找到了同名的成員函數,則停止查找,否則沿著繼承鏈向上繼續(xù)查找。派生中的同名函數阻止編譯器到其基類繼續(xù)查找,這就是出現同名覆蓋和隱藏現象的原因。從成員函數調用的查找方法可知,同名覆蓋和隱藏基類函數的原因是由于編譯器在派生類中遇到同名函數后不再到基類中繼續(xù)查找。然而,在派生類中可利用作用域標識符(::)直接調用基類的同名成員函數,方式如下:[<派生類對象名>.]<基類名>::<函數名>6.2派生類:定義及相關技術【例6-3】派生類中成員函數的同名覆蓋、隱藏和重載示例。6.2派生類:定義及相關技術6.2.4派生類與基類的賦值兼容由于派生類中包含從基類繼承的成員,因此在任何需要基類對象的地方都可以用公有派生類的對象來代替。派生類對象向基類對象、指針或引用賦值滿足以下兼容規(guī)則:派生類對象可以賦值給基類對象,它是把派生類對象中從對應基類中繼承來的成員賦值給基類對象。派生類對象的地址可以賦給指向基類的指針變量,即基類指針可以指向派生類對象。但通過該指針只能訪問派生類中從基類繼承的成員,不能訪問派生類中的新增成員。派生類對象可以代替基類對象向基類對象的引用進行賦值或初始化。但它只能引用包含在派生類對象中基類部分的成員。6.2派生類:定義及相關技術
在對基類對象進行適當的轉換或增添成員函數后,基類對象能向派生類對象、指針或引用賦值。由于從基類轉換來的派生類對象缺少派生類中新增的數據成員,因而訪問指向基類對象的派生類指針(或引用)是不安全的。下面列出兩種轉換方法。(1)在派生類中定義正確的轉換構造函數或賦值運算符重載函數,則能確保將基類對象賦給派生類對象語句通過編譯。此時,派生類對象中數據成員的內容與所定義的構造函數或賦值運算符重載函數相關。6.2派生類:定義及相關技術(2)用強制類型轉換運算符轉換基類對象為派生類對象并賦給派生類指針或引用,格式如下:<派生類對象指針>=static_cast<派生類*>(&<基類對象>);<派生類>&<派生類引用>=static_cast<派生類&>(<基類對象>);其中static_cast運算符的使用格式為static_cast<類型名>(<表達式>),功能是把<表達式>轉換為<類型名>的類型。用static_cast運算符能實現類層次結構中基類(父類)和派生類(子類)之間指針或引用的轉換。這種轉換分為“上行”和“下行”兩種。注意:將強制類型轉換后的基類對象賦值給派生類的指針或引用,由于缺少派生類的成員,可能會導致程序崩潰。6.2派生類:定義及相關技術【例6-4】設計Person類和其派生類Student類,驗證賦值兼容規(guī)則。
6.2派生類:定義及相關技術(1)在程序中,Student類是Person類的派生類,它在基類數據成員的基礎上增加了學號和入學成績數據成員。類中showInfo成員函數用于顯示對象中的數據。(2)主函數的最后一條語句studentPtr=&personObj;在編譯時出錯。錯誤信息為:errorC2440:“=”:無法從“Person*”轉換為“Student*”。說明基類對象地址直接賦給派生類指針不支持。如果改為studentPtr=static_cast<Student*>(&personObj);,則能通過編譯。(3)displayPersonInfo函數的形參為Person類的引用類型,在主程序中分別將基類對象personObj和派生類對象studentObj傳遞給該函數,運行結果顯示其只能調用基類中的成員函數showInfo,均只能見到Person類的部分數據。(4)personObj=studentObj;語句的結果是personObj中數據成員的值和studentObj中基類部分數據成員的值完全相同。6.3派生類的構造與析構在派生類對象中,數據成員分為兩類:一類是繼承于基類的數據成員;另一類是新添加的數據成員,包含其他類的成員對象。派生類對象中數據成員繼承了基類數據,因而構造函數需要負責它們的初始化。C++規(guī)定,基類成員的初始化工作由基類的構造函數完成,而派生類的初始化工作由派生類的構造函數完成。派生類構造函數的定義格式如下:派生類名(<參數總表>):基類名1(<參數表1>)[,...,基類名m(<參數表m>),成員對象名1(<成員對象參數表1>),...,成員對象名n(<成員對象參數表n>)]{ <派生類新增成員的初始化>;}6.3派生類的構造與析構其中:(1)基類名1(<參數表1>),...,基類名m(<參數表m>)為基類成員的初始化表,成員對象名1(<成員對象參數表1>),...,成員對象名n(<成員對象參數表n>)為成員對象初始化表。派生類中新增的類型為基本類型的數據成員,也可采用成員對象的方式進行初始化。(2)派生類構造函數中所列出的基類名i(<參數表i>),在基類中需要有相匹配的構造函數。<參數總表>中包含其所有基類、成員對象和新增成員初始化所需的參數。(3)冒號后面的基類名和對象名之間用逗號分隔,其順序沒有嚴格的限制。由于基類和派生類都需要調用構造函數來實現初始化成員,這就產生了派生類構造函數和析構函數的執(zhí)行順序問題。在創(chuàng)建派生類對象時,構造函數的調用順序為:①按照在派生類定義時的先后次序調用基類構造函數。②按照在類定義中排列的先后順序依次調用成員對象的構造函數。③執(zhí)行派生類構造函數中的操作。派生類對象在撤消時是按照構造函數調用相反的次序調用類的析構函數。首先調用派生類析構函數,清除派生類中新增的數據成員;其次調用成員對象析構函數,清除派生類對象中的成員對象;最后調用基類的析構函數,清除從基類繼承來的數據成員。6.3派生類的構造與析構【例6-5】設計Teacher類,它繼承于Person類并組合了Date類。演示派生類對象在構造和析構時,基類和成員對象構造與析構函數的調用情況。程序說明:從程序運行結果可見,雖然在Teacher派生類構造函數定義中成員對象(dateOfWork)聲明在基類(Person)前,但依然是基類構造函數先被執(zhí)行。此外,運行結果顯示析構函數的調用次序正好與構造函數調用順序相反。派生類構造Teacher(char*n,bools,inty,intm,intd,inten,char*pt)的總參數表中參數的包括基類構造函數Person(char*n,bools)和成員對象構造函數Date(inty,intm,intd)的參數。在派生類構造函數定義中,基類Person的聲明格式是Person(n,s),用Date類定義的成員對象dateOfWork的聲明格式是dateOfWork(y,m,d)。6.3派生類的構造與析構
C++支持從兩個及以上基類共同派生出新的派生類,這種繼承結構被稱為多重繼承(MultipleInheritance)或多繼承。多重繼承能方便地描述事物的多種特征,能方便地支持代碼復用,具有結構簡單清晰的優(yōu)點。6.4多重繼承與虛基類
6.4多重繼承與虛基類6.4.1多重繼承
多重繼承的派生類繼承于多個基類,在派生類定義時,多個基類之間用逗號分隔。派生類對象初始化時,將首先調用基類的構造函數,其調用順序是參照定義中的次序,如:classC:publicA,publicB{public: C():B(),A(){cout<<"CallCConstructor!"<<endl;}};
基類A的構造函數先調用,盡管在構造函數聲明中基類B的構造函數在基類A的前面。
6.4多重繼承與虛基類由于多重繼承的基類不止一個,而不同的類其數據成員和成員函數有可能同名,此時派生類繼承了不同基類的同名成員,會出現無法訪問的二義性問題?!纠?-6】手機類和MP4播放器類為基類定義音樂手機類,并測試。
6.4多重繼承與虛基類程序說明:MobilePhone類和MusicPlayer類均擁有show成員函數,在派生類中訪問show函數必須的指明是屬于哪個基類的成員函數,方法是MobilePhone::show();,其中“::”是作用域標識符。語句myObj.show();在編譯時出錯,所報錯誤為:對“show”的訪問不明確。如果將改語句為myObj.MusicPlayer::show();,則能通過編譯。6.4多重繼承與虛基類6.4.2虛基類
在例程6-6中,手機類和播放器類均含有商標和價格數據成員,并且在派生類中包含了兩份同樣的數據。這種設計不僅浪費存儲空間,而且會帶來數據更新的一致性問題。例如,若音樂手機降價了,則需要同時修改兩處price私有數據。一種比較自然的設計方法是定義一個商品類,其中包含商標和價格數據,而手機類和播放器類分別繼承于商品類。派生類的層次結構如圖所示。6.4多重繼承與虛基類在多重繼承的類繼承層次結構中,繼承于兩個不同基類的派生類,由于其基類又派生于同一個基類(不一定是直接基類),故可能出現如圖6-5所示的“鉆石繼承”(又稱菱形繼承)情況。此時商品類中的數據成員(如價格price)分別被其派生類手機類和播放器類所繼承,而音樂手機類又多重繼承于手機類和播放器類,因此,商品類的數據成員price分別通過手機類和播放器類派生給音樂手機類,同樣的數據成員在音樂手機派生類對象中將出現兩個,并且存儲地址也不相同。這樣不僅浪費存儲空間,而且還會因為需要維護數據的一致性增加額外的開銷。下面的示例說明了多重繼承可能引發(fā)“鉆石繼承”問題?!纠?-7】多重繼承中存在的“鉆石繼承”和數據同步問題示例。6.4多重繼承與虛基類跟蹤與觀察:(1) 主函數中執(zhí)行了myObj.MusicPlayer::setPrice(500);,使得繼承于MusicPlayer的price數據的值為500,因而運行結果顯示出1800和500兩個不同的價格。(2) 從圖6-6可知,基類繼承來的數據成員name和price在音樂手機派生類對象myObj中分別存儲了兩份,其中,從MobilePhone類繼承的name成員的存儲地址為0x002ff85c,price成員的存儲地址為0x002ff87c,而從MusicPlayer類繼承的name成員的存儲地址為0x002ff8a0,price成員的存儲地址為0x002ff8c0,并且兩個price成員的值不相同。6.4多重繼承與虛基類多重繼承中存在的鉆石繼承結構將導致基類的數據成員在派生類對象中重復出現。為解決多重繼承在路徑匯聚點上的派生類因從不同路徑繼承了某個基類多次而產生重復繼承的問題,C++語言通過引入虛基類(VirtualBaseClass)來支持派生類對象在內存中僅有基類數據成員的一份拷貝,以消除鉆石繼承所產生的數據重復存儲問題。虛基類定義的語法非常簡單,只需用virtual限定符在派生類定義時將基類的繼承方式聲明為虛擬的即可。例如:classMobilePhone:virtualpublicMerchandise{...}其中virtual和public關鍵字的次序可任意。6.4多重繼承與虛基類下面的程序是在例6-7的基礎上,通過定義虛基類解決派生類對象中基類數據成員重復存儲的問題?!纠?-8】用虛基類解決“鉆石繼承”問題。
6.4多重繼承與虛基類跟蹤與觀察:(1) 從圖可知,myObj對象中從不同路徑繼承的數據成員name和
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年三元催化凈化器項目發(fā)展計劃
- 腕關節(jié)活動的主動肌
- 美國研究生院留學咨詢代理合作協(xié)議
- 基金投資擔保補充協(xié)議
- 快手直播基地內容審核與版權保護合作協(xié)議
- 寵物診療機構獸醫(yī)助理長期合作協(xié)議
- 社區(qū)環(huán)保材料回收站場地租賃及環(huán)保設備采購與環(huán)??萍紕?chuàng)新協(xié)議
- 高清影視拍攝軌道車租賃與數字修復合同
- 藥品專利布局與知識產權運營管理協(xié)議
- 建筑工程合同檔案數字化管理及評估協(xié)議
- 汽車起重機日常檢查維修保養(yǎng)記錄表
- 防銷售誤導分解專題培訓課件
- 《中醫(yī)藥康復專業(yè)英語課件》
- 銀行特殊消費者群體金融服務工作指引
- 說文解字全文
- 嬰兒氣道異物急救評分標準
- 執(zhí)業(yè)醫(yī)師X線讀片教學課件
- 工程安全生產事故報告處理制度
- 催乳師職業(yè)培訓考試試題與答案
- 2023年一般行業(yè)主要負責人和安全管理人員考試復習題庫(含答案)
- 護理部運用PDCA縮短門診患者超聲檢查等候時間品管圈QCC成果匯報
評論
0/150
提交評論