日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++继承构造函数

發(fā)布時間:2024/4/18 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++继承构造函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【1】為什么需要繼承構(gòu)造函數(shù)?

首先,看看如下代碼片段:

1 struct A2 { 3 A(int i)4 {} 5 }; 6 7 struct B : A8 { 9 B(int i) : A(i) 10 {} 11 };

在C++中非常常見:B派生于A,B在構(gòu)造函數(shù)中調(diào)用A的構(gòu)造函數(shù),從而完成構(gòu)造函數(shù)的“傳遞”。

有時候,基類可能擁有數(shù)量眾多的不同版本的構(gòu)造函數(shù)(這樣的情況并不少見)。

那么,倘若基類中有大量的構(gòu)造函數(shù),而派生類卻只有一些成員函數(shù)時,那么對于派生類而言,其構(gòu)造就等同于構(gòu)造基類。

為了遵從語法規(guī)則,就需要寫很多的“透傳”的構(gòu)造函數(shù)。如下面這個例子:

struct A {A(int i) {} A(double d, int i) {} A(float f, int i, const char* c) {} // ... }; struct B : A { B(int i) : A(i) {}B(double d, int i) : A(d, i) {}B(float f, int i, const char* c) : A(f, i, c) {} // ... virtual void ExtraInterface() {} };

在構(gòu)造B的時候想要擁有A這樣多的構(gòu)造方法的話,就必須一—“透傳”各個接口。這無疑是相當(dāng)不方便的。

而引入繼承構(gòu)造函數(shù)的機(jī)制就是為了解決這種麻煩的。

【2】using聲明

我們知道C++中已經(jīng)有一個好用的規(guī)則:

如果派生類要使用基類的成員函數(shù)(被隱藏)的話,可以通過using聲明(using-declaration)來完成。請看如下示例:

(1)不聲明基類成員函數(shù):

基類成員函數(shù)被隱藏(關(guān)于隱藏可以參考《重載、覆蓋、隱藏》),在派生類中不做聲明:

1 #include <iostream>2 using namespace std;3 4 struct Base5 { 6 void f(double i)7 { 8 cout << "Base:" << i << endl;9 } 10 }; 11 12 struct Derived : Base 13 { 14 // using Base::f; // 聲明基類Base的f函數(shù) 15 void f(int i) 16 { 17 cout << "Derived:" << i << endl; 18 } 19 }; 20 21 int main() 22 { 23 Base b; 24 b. f(4.5); 25 Derived d; 26 d. f(4.5); 27 } 28 29 /* 30 Base:4.5 31 Derived:4 32 */

編譯警告:warning C4244 : “參數(shù)”: 從“double”轉(zhuǎn)換到“int”,可能丟失數(shù)據(jù)

再結(jié)合運(yùn)行結(jié)果分析,說明執(zhí)行的是派生類Derived中參數(shù)為int類型的函數(shù)f。

(2)聲明基類成員函數(shù):

1 #include <iostream>2 using namespace std;3 4 struct Base5 { 6 void f(double i)7 { 8 cout << "Base:" << i << endl;9 } 10 }; 11 12 struct Derived : Base 13 { 14 using Base::f; // 聲明繼承基類Base的f函數(shù) 15 void f(int i) 16 { 17 cout << "Derived:" << i << endl; 18 } 19 }; 20 21 int main() 22 { 23 Base b; 24 b. f(4.5); 25 Derived d; 26 d. f(4.5); 27 } 28 29 /* 30 Base:4.5 31 Base:4.5 32 */

編譯無警告,再結(jié)合運(yùn)行結(jié)果分析:

說明執(zhí)行的是基類Base中參數(shù)為double類型的函數(shù)f。

同時,可以看到派生類Derived中其實(shí)有兩個f函數(shù)的版本。

經(jīng)過以上的分析,在C++11中,這個特性被擴(kuò)展到了構(gòu)造函數(shù)上。

即派生類可以通過使用using聲明來繼承基類的構(gòu)造函數(shù)。

【3】應(yīng)用繼承構(gòu)造函數(shù)

如上示例1,應(yīng)用繼承構(gòu)造函數(shù),改造如下:

1 #include <iostream>2 using namespace std;3 4 struct A5 {6 A(int i = 10) : m_a(i)7 {}8 9 int m_a; 10 }; 11 12 struct B : A 13 { 14 using A::A; // 繼承構(gòu)造函數(shù) 15 16 int m_b{ 100 }; 17 }; 18 19 int main() 20 { 21 B b; 22 cout << b.m_a << endl; // 10 23 cout << b.m_b << endl; // 100 24 25 B bb(200); 26 cout << bb.m_a << endl; // 200 27 cout << bb.m_b << endl; // 100 28 }

通過using A::A的聲明,把基類中的構(gòu)造函數(shù)全部繼承到派生類B中。

應(yīng)用注意項(xiàng):

(1)C++11標(biāo)準(zhǔn)更精巧的是,繼承構(gòu)造函數(shù)被設(shè)計(jì)為跟派生類中的各種類默認(rèn)函數(shù)(默認(rèn)構(gòu)造、析構(gòu)、拷貝構(gòu)造等)一樣,是隱式聲明的。

這意味著如果一個繼承構(gòu)造函數(shù)不被相關(guān)代碼使用,編譯器不會為其產(chǎn)生真正的函數(shù)代碼。

這無疑比“透傳”方案總是生成派生類的各種構(gòu)造函數(shù)更加節(jié)省目標(biāo)代碼空間。

(2)繼承構(gòu)造函數(shù)只會初始化基類中成員變量,對于派生類中的成員變量,則無能為力。

不過配合C++11中類成員的初始化表達(dá)式,為派生類成員變量設(shè)定一個默認(rèn)值還是沒有問題的。

比如此例中的m_b成員變量,設(shè)定默認(rèn)值為100。

(3)基類構(gòu)造函數(shù)的參數(shù)可能會有默認(rèn)值。

對于繼承構(gòu)造函數(shù)來講,基類構(gòu)造函數(shù)參數(shù)的默認(rèn)值是不會被繼承的。

比如此例中的bb對象,利用實(shí)參200進(jìn)行構(gòu)造對象,結(jié)果m_a的值為200,而不是默認(rèn)的10。

(4)基類構(gòu)造函數(shù)有默認(rèn)值會導(dǎo)致基類產(chǎn)生多個構(gòu)造函數(shù)的版本,這些版本都會被派生類繼承。

比如此例中,事實(shí)上,構(gòu)建對象b,使用的均是默認(rèn)構(gòu)造函數(shù);構(gòu)建對象bb,使用的均是帶一個參數(shù)的構(gòu)造函數(shù)版本。

(5)有的時候,還會遇到繼承構(gòu)造函數(shù)“沖突”的情況。這通常發(fā)生在派生類擁有多個基類的時候。

多個基類中的部分構(gòu)造函數(shù)可能導(dǎo)致派生類中的繼承構(gòu)造函數(shù)的函數(shù)名、參數(shù)(有的時候,我們也稱其為函數(shù)簽名)都相同,

那么繼承類中的沖突的繼承構(gòu)造函數(shù)將導(dǎo)致不合法的派生類代碼,如下示例:

1 struct A { A(int) {} }; 2 3 struct B { B(int) {} }; 4 5 struct C : A, B 6 { 7 using A::A; 8 using B::B; 9 };

這種情況下,可以通過顯式定義繼承類的沖突的構(gòu)造函數(shù),阻止隱式生成相應(yīng)的繼承構(gòu)造函數(shù)來解決沖突:

1 struct A { A(int) {} }; 2 3 struct B { B(int) {} }; 4 5 struct C : A, B 6 { 7 C(int c) : A(c), B(c) 8 {} 9 };

(6)如果基類的構(gòu)造函數(shù)被聲明為私有成員函數(shù),或者派生類是從基類中虛繼承的,那么就不能夠在派生類中聲明繼承構(gòu)造函數(shù)。

(7)如果基類的構(gòu)造函數(shù)沒有默認(rèn)構(gòu)造函數(shù),那么一旦使用了繼承構(gòu)造函數(shù),編譯器也不會再為派生類生成默認(rèn)構(gòu)造函數(shù)。

如下示例不能夠通過編譯:

1 struct A 2 { 3 A(int) {} 4 };5 6 struct B : A 7 { 8 using A::A; 9 }; 10 11 int main() 12 { 13 B objB; // C2280 “B::B(void)”: 嘗試引用已刪除的函數(shù) 14 }

個人認(rèn)為,解決這種問題有兩種方式,代碼如下:

1 #if 0 // 方式一:基類定義默認(rèn)構(gòu)造函數(shù),派生類自然也就有了2 struct A { A(int a = 10) {} };3 struct B : A4 {5 using A::A;6 };7 #else // 方式二:派生類自定義默認(rèn)構(gòu)造函數(shù)8 struct A { A(int) {} };9 struct B : A 10 { 11 using A::A; 12 B(int c = 20) : A(c) 13 {} 14 }; 15 #endif 16 17 int main() 18 { 19 B objB; 20 }

如上所述。

good good study, day day up.

順序 選擇 循環(huán) 總結(jié)

總結(jié)

以上是生活随笔為你收集整理的c++继承构造函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。