詳解C++編程中的私有繼承和公有繼承
C++類(lèi)的私有繼承
在聲明一個(gè)派生類(lèi)時(shí)將基類(lèi)的繼承方式指定為private的,稱(chēng)為私有繼承,用私有繼承方式建立的派生類(lèi)稱(chēng)為私有派生類(lèi)(private derived class ), 其基類(lèi)稱(chēng)為私有基類(lèi)(private base class )。
私有基類(lèi)的公用成員和保護(hù)成員在派生類(lèi)中的訪(fǎng)問(wèn)屬性相當(dāng)于派生類(lèi)中的私有成員,即派生類(lèi)的成員函數(shù)能訪(fǎng)問(wèn)它們,而在派生類(lèi)外不能訪(fǎng)問(wèn)它們。私有基類(lèi)的私有成員在派生類(lèi)中成為不可訪(fǎng)問(wèn)的成員,只有基類(lèi)的成員函數(shù)可以引用它們。一個(gè)基類(lèi)成員在基類(lèi)中的訪(fǎng)問(wèn)屬性和在派生類(lèi)中的訪(fǎng)問(wèn)屬性可能是不同的。私有基類(lèi)的成員在私有派生類(lèi)中的訪(fǎng)問(wèn)屬性見(jiàn)下表。
上表不必死記硬背,只需理解:既然聲明為私有繼承,就表示將原來(lái)能被外界引用的成員隱藏起來(lái),不讓外界引用,因此私有基類(lèi)的公用成員和保護(hù)成員理所當(dāng)然地成為派生類(lèi)中的私有成員。
私有基類(lèi)的私有成員按規(guī)定只能被基類(lèi)的成員函數(shù)引用,在基類(lèi)外當(dāng)然不能訪(fǎng)問(wèn)他們,因此它們?cè)谂缮?lèi)中是隱蔽的,不可訪(fǎng)問(wèn)的。
對(duì)于不需要再往下繼承的類(lèi)的功能可以用私有繼承方式把它隱蔽起來(lái),這樣,下一層的派生類(lèi)無(wú)法訪(fǎng)問(wèn)它的任何成員。可以知道,一個(gè)成員在不同的派生層次中的訪(fǎng)問(wèn)屬性可能是不同的,它與繼承方式有關(guān)。
[例]
class Student1: private Student//用私有繼承方式聲明派生類(lèi)Student1 { public: void display_1( ) //輸出兩個(gè)數(shù)據(jù)成員的值 { cout<<"age: "<<age<<endl; //引用派生類(lèi)的私有成員,正確 cout<<"address: "<<addr<<endl; } //引用派生類(lèi)的私有成員,正確 private: int age; string addr; };
請(qǐng)分析下面的主函數(shù):
int main( ) { Student1 stud1;//定義一個(gè)Student1類(lèi)的對(duì)象stud1 stud1.display(); //錯(cuò)誤,私有基類(lèi)的公用成員函數(shù)在派生類(lèi)中是私有函數(shù) stud1.display_1( );//正確,Display_1函數(shù)是Student1類(lèi)的公用函數(shù) stud1.age=18; //錯(cuò)誤,外界不能引用派生類(lèi)的私有成員 return 0; }
可以看到:
不能通過(guò)派生類(lèi)對(duì)象(如stud1)引用從私有基類(lèi)繼承過(guò)來(lái)的任何成員(如stud1.display()或stud1.num)。
派生類(lèi)的成員函數(shù)不能訪(fǎng)問(wèn)私有基類(lèi)的私有成員,但可以訪(fǎng)問(wèn)私有基類(lèi)的公用成員(如stud1.display_1函數(shù)可以調(diào)用基類(lèi)的公用成員函數(shù)display,但不能引用基類(lèi)的私有成員num)。
不少讀者提出這樣一個(gè)問(wèn)題:私有基類(lèi)的私有成員mun等數(shù)據(jù)成員只能被基類(lèi)的成員函數(shù)引用,而私有基類(lèi)的公用成員函數(shù)又不能被派生類(lèi)外調(diào)用,那么,有沒(méi)有辦法調(diào)用私有基類(lèi)的公用成員函數(shù),從而引用私有基類(lèi)的私有成員呢?有。
應(yīng)當(dāng)注意到,雖然在派生類(lèi)外不能通過(guò)派生類(lèi)對(duì)象調(diào)用私有基類(lèi)的公用成員函數(shù),但可以通過(guò)派生類(lèi)的成員函數(shù)調(diào)用私有基類(lèi)的公用成員函數(shù)(此時(shí)它是派生類(lèi)中的私有成員函數(shù),可以被派生類(lèi)的任何成員函數(shù)調(diào)用)。
可將上面的私有派生類(lèi)的成員函數(shù)定義改寫(xiě)為:
void display_1( )//輸出5個(gè)數(shù)據(jù)成員的值 { display(): //調(diào)用基類(lèi)的公用成員函數(shù),輸出3個(gè)數(shù)據(jù)成員的值 cout<<"age: "<<age<<endl; //輸出派生類(lèi)的私有數(shù)據(jù)成員 cout<<"address: "<<addr<<endl; } //輸出派生類(lèi)的私有數(shù)據(jù)成員
main函數(shù)可改寫(xiě)為:
int main( ) { Student1 stud1; stud1.display_1( );//display_1函數(shù)是派生類(lèi)Student1類(lèi)的公用函數(shù) return 0; }
這樣就能正確地引用私有基類(lèi)的私有成員??梢钥吹?,本例采用的方法是:
在main函數(shù)中調(diào)用派生類(lèi)中的公用成員函數(shù)stud1.display_1;
通過(guò)該公用成員函數(shù)調(diào)用基類(lèi)的公用成員函數(shù)display(它在派生類(lèi)中是私有函數(shù),可以被派生類(lèi)中的任何成員函數(shù)調(diào)用);
通過(guò)基類(lèi)的公用成員函數(shù)display引用基類(lèi)中的數(shù)據(jù)成員。
請(qǐng)根據(jù)上面的要求,補(bǔ)充和完善上面的程序,使之成為完整、正確的程序,程序中應(yīng)包括輸入數(shù)據(jù)的函數(shù)。
由于私有派生類(lèi)限制太多,使用不方便,一般不常使用。
C++類(lèi)的公用繼承
在定義一個(gè)派生類(lèi)時(shí)將基類(lèi)的繼承方式指定為public的,稱(chēng)為公用繼承,用公用繼承方式建立的派生類(lèi)稱(chēng)為公用派生類(lèi)(public derived class ),其基類(lèi)稱(chēng)為公用基類(lèi)(public base class )。
采用公用繼承方式時(shí),基類(lèi)的公用成員和保護(hù)成員在派生類(lèi)中仍然保持其公用成員和保護(hù)成員的屬性,而基類(lèi)的私有成員在派生類(lèi)中并沒(méi)有成為派生類(lèi)的私有成員,它仍然是基類(lèi)的私有成員,只有基類(lèi)的成員函數(shù)可以引用它,而不能被派生類(lèi)的成員函數(shù)引用,因此就成為派生類(lèi)中的不可訪(fǎng)問(wèn)的成員。公用基類(lèi)的成員在派生類(lèi)中的訪(fǎng)問(wèn)屬性見(jiàn)表。
有人問(wèn),既然是公用繼承,為什么不讓訪(fǎng)問(wèn)基類(lèi)的私有成員呢?要知道,這是C++中一個(gè)重要的軟件工程觀(guān)點(diǎn)。因?yàn)樗接谐蓡T體現(xiàn)了數(shù)據(jù)的封裝性,隱藏私有成員有利于測(cè)試、調(diào)試和修改系統(tǒng)。如果把基類(lèi)所有成員的訪(fǎng)問(wèn)權(quán)限都原封不動(dòng)地繼承到派生類(lèi),使基類(lèi)的私有成員在派生類(lèi)中仍保持其私有性質(zhì),派生類(lèi)成員能訪(fǎng)問(wèn)基類(lèi)的私有成員,那么豈非基類(lèi)和派生類(lèi)沒(méi)有界限了?這就破壞了基類(lèi)的封裝性。如果派生類(lèi)再繼續(xù)派生一個(gè)新的派生類(lèi),也能訪(fǎng)問(wèn)基類(lèi)的私有成員,那么在這個(gè)基類(lèi)的所有派生類(lèi)的層次上都能訪(fǎng)問(wèn)基類(lèi)的私有成員,這就完全丟棄了封裝性帶來(lái)的好處。保護(hù)私有成員是一條重要的原則。
[例] 訪(fǎng)問(wèn)公有基類(lèi)的成員。下面寫(xiě)出類(lèi)的聲明部分:
Class Student//聲明基類(lèi) { public: //基類(lèi)公用成員 void get_value( ) { cin>>num>>name>>sex; } void display( ) { cout<<" num: "<<num<<endl; cout<<" name: "<<name<<endl; cout<<" sex: "<<sex<<endl; } private: //基類(lèi)私有成員 int num; string name; char sex; }; class Student1: public Student //以public方式聲明派生類(lèi)Student1 { public: void display_1( ) { cout<<" num: "<<num<<endl; //企圖引用基類(lèi)的私有成員,錯(cuò)誤 cout<<" name: "<<name<<endl; //企圖引用基類(lèi)的私有成員,錯(cuò)誤 cout<<" sex: "<<sex<<endl; //企圖引用基類(lèi)的私有成員,錯(cuò)誤 cout<<" age: "<<age<<endl; //引用派生類(lèi)的私有成員,正確 cout<<" address: "<<addr<<endl; } //引用派生類(lèi)的私有成員,正確 private: int age; string addr; };
由于基類(lèi)的私有成員對(duì)派生類(lèi)來(lái)說(shuō)是不可訪(fǎng)問(wèn)的,因此在派生類(lèi)中的display_1函數(shù)中直接引用基類(lèi)的私有數(shù)據(jù)成員num,name和sex是不允許的。只能通過(guò)基類(lèi)的公用成員函數(shù)來(lái)引用基類(lèi)的私有數(shù)據(jù)成員??梢詫⑴缮?lèi)Student1的聲明改為
class Student1: public Student //以public方式聲明派生類(lèi)Student1 { public: void display_1( ) { cout<<" age: "<<age<<endl; //引用派生類(lèi)的私有成員,正確 cout<<" address: "<<addr<<endl; //引用派生類(lèi)的私有成員,正確 } private: int age; string addr; };
然后在main函數(shù)中分別調(diào)用基類(lèi)的display函數(shù)和派生類(lèi)中的display_1函數(shù),先后輸出5個(gè)數(shù)據(jù)。
可以這樣寫(xiě)main函數(shù)(假設(shè)對(duì)象stud中已有數(shù)據(jù)):
int main( ) { Student1 stud;//定義派生類(lèi)Student1的對(duì)象stud stud.display( ); //調(diào)用基類(lèi)的公用成員函數(shù),輸出基類(lèi)中3個(gè)數(shù)據(jù)成員的值 stud.display_1(); //調(diào)用派生類(lèi)公用成員函數(shù),輸出派生類(lèi)中兩個(gè)數(shù)據(jù)成員的值 return 0; }
請(qǐng)根據(jù)上面的分析,寫(xiě)出完整的程序,程序中應(yīng)包括輸入數(shù)據(jù)的函數(shù)。
實(shí)際上,程序還可以改進(jìn),在派生類(lèi)的display_1函數(shù)中調(diào)用基類(lèi)的display函數(shù),在主函數(shù)中只要寫(xiě)一行:
stud.display_1();
即可輸出5個(gè)數(shù)據(jù)。
上一篇:簡(jiǎn)單介紹C++編程中派生類(lèi)的析構(gòu)函數(shù)
欄 目:C語(yǔ)言
本文標(biāo)題:詳解C++編程中的私有繼承和公有繼承
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2696.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10求子數(shù)組最大和的解決方法詳解
- 01-10深入二叉樹(shù)兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車(chē)次數(shù)的問(wèn)題詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-用棧實(shí)現(xiàn)表達(dá)式求值的方法詳解
- 01-10HDOJ 1443 約瑟夫環(huán)的最新應(yīng)用分析詳解
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10如何查看進(jìn)程實(shí)際的內(nèi)存占用情況詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改