子類為完成基類初始化,在c++11之前,需要在初始化列表呼叫基類的建構函式,從而完成建構函式的傳遞。如果基類擁有多個建構函式,那麼子類也需要實現多個與基類建構函式對應的建構函式。
1class
base
25 base(char c) : m_c(c), m_value(0
) {}
6private:7
intm_value;
8char
m_c;9};
1011
class derived : public
base
1216 derived(char
c) : base(c) {}
1718
//假設派生類只是新增了乙個普通的函式
19void
display()
2023 };
書寫多個派生類建構函式只為傳遞引數完成基類的初始化,這種方式無疑給開發人員帶來麻煩,降低了編碼效率。從c++11開始,推出了繼承建構函式(inheriting constructor),使用using來宣告繼承基類的建構函式,我們可以這樣書寫。
1class
base
4 base(char c) : m_c(c), m_value(0
) {}
5private:6
intm_value;
7char
m_c;8};
910class derived : public
base
17 };
上面**中,我們通過using base::base把基類建構函式繼承到派生類中,不再需要書寫多個派生類建構函式來完成基類的初始化。更為巧妙的是,c++11標準規定,繼承建構函式與類的一些預設函式(預設構造、析構、拷貝建構函式等)一樣,是隱式宣告,如果乙個繼承建構函式不被相關**使用,編譯器不會為其產生真正的函式**。這樣比通過派生類建構函式「透傳構造函式引數」來完成基類初始化的方案,總是需要定義派生類的各種建構函式更加節省目標**空間。
(2)建構函式擁有預設值會產生多個建構函式版本,且繼承建構函式無法繼承基類建構函式的預設引數,所以我們在使用有預設引數建構函式的基類時就必須要小心。
1classa 4
void display() 5}
67private:8
intm_a;
9double
m_b;
10};
1112
class b : public
a ;
那麼a中的建構函式會有下面幾個版本:
a()a(int)
a(int,double)
a(consta&)
那麼b中對應的繼承建構函式將會包含如下幾個版本:
b()b(int)
b(int,double)
b(constb&)
可以看出,引數預設值會導致多個建構函式版本的產生,因此在使用時需格外小心。
(3)多繼承的情況下,繼承建構函式會出現「衝突」的情況,因為多個基類中的部分建構函式可能導致派生類中的繼承建構函式的函式名、引數(即函式簽名)相同。考察如下**:
1classa 4
};56classb7
10};
1112
class c : public a, public
b 19 };
為避免繼承建構函式衝突,可以通過顯示定義繼承類衝突的建構函式,組織隱式生成相應的繼承建構函式。
此外,使用繼承建構函式時,還需要注意以下幾點:
如果基類建構函式被申明為私有成員函式,或者派生類是從基類中虛繼承的 ,那麼就不能在派生類中申明繼承建構函式;
一旦使用繼承建構函式,編譯器就不會再為派生類生成預設建構函式了。
C primer 第十六章 繼承建構函式
異常處理 直接上 trycatch runtime error e pragma once include item base.hpp include handle.hpp class sales item sales item const item base item h item.clone i...
Java基礎查漏補缺 繼承中的子父類建構函式
在子父類的建構函式中存在以下關係 1 在呼叫子類建構函式時,父類建構函式也會執行 因為在子類建構函式中,隱式地認為第一行為super 即呼叫父類的無引數構造方法。如果父類沒有無引數構造方法,那麼需要在子類中給出父類的含參構造方法。如果父類中沒有建構函式,那麼子類中就無需給出任何父類的建構函式。2 如...
建構函式的繼承
在父類中定義了2個建構函式,在子類中,也定義了2個建構函式。當執行子類時,可以發現先呼叫父類的建構函式,在呼叫子類的建構函式。實驗四 建構函式的繼承 實驗內容 在父類中,定義了2個建構函式,在子類中,也定義了2個建構函式。編寫 程式顯示父類 子類建構函式的呼叫過程,在子類中實現建構函式的繼承。pac...