子類為完成基類初始化,在c++11之前,需要在初始化列表呼叫基類的建構函式,從而完成建構函式的傳遞。如果基類擁有多個建構函式,那麼子類也需要實現多個與基類建構函式對應的建構函式。
classbase
base(
char c) : m_c(c), m_value(0
) {}
private
:
intm_value;
char
m_c;
}; class derived : public
base
derived(
char
c) : base(c) {}
//假設派生類只是新增了乙個普通的函式
void
display()
};
書寫多個派生類建構函式只為傳遞引數完成基類的初始化,這種方式無疑給開發人員帶來麻煩,降低了編碼效率。從c++11開始,推出了繼承建構函式(inheriting constructor),使用using來宣告繼承基類的建構函式,我們可以這樣書寫。
classbase
base(char c) : m_c(c), m_value(0
) {}
private
:int
m_value;
char
m_c;
};class derived : public
base
};
上面**中,我們通過using base::base把基類建構函式繼承到派生類中,不再需要書寫多個派生類建構函式來完成基類的初始化。更為巧妙的是,c++11標準規定,繼承建構函式與類的一些預設函式(預設構造、析構、拷貝建構函式等)一樣,是隱式宣告,如果乙個繼承建構函式不被相關**使用,編譯器不會為其產生真正的函式**。這樣比通過派生類建構函式「透傳構造函式引數」來完成基類初始化的方案,總是需要定義派生類的各種建構函式更加節省目標**空間。
注意事項!!!
1.建構函式擁有預設值會產生多個建構函式版本,且繼承建構函式無法繼承基類建構函式的預設引數,所以我們在使用有預設引數建構函式的基類時就必須要小心。(即建構函式使用初始化列表是給類屬性賦值的,其中也可以自動預設值,如果帶了預設值的話,該類的建構函式就包含多個建構函式了,因為實現的時候回使用預設值替代缺少的)
例子:
classa
void display()
} private
:
intm_a;
double
m_b;
}; class b : public
a ;
那麼a中的建構函式會有下面幾個版本:
a()a(int)a(
int,double
)a(consta&)
那麼b中對應的繼承建構函式將會包含如下幾個版本://繼承建構函式無法繼承基類建構函式的引數,但是建構函式乙個也不少
b()b(int)b(
int,double
)b(constb&)
2.多繼承的情況下,繼承建構函式會出現「衝突」的情況,因為多個基類中的部分建構函式可能導致派生類中的繼承建構函式的函式名、引數(即函式簽名)相同。考察如下**:
classa };
classb
}; class c : public a, public
b };
為避免繼承建構函式衝突,可以通過顯示定義繼承類衝突的建構函式,組織隱式生成相應的繼承建構函式。(感覺還是老老實實的寫普通的繼承吧,不要寫繼承構造)
C 建構函式的繼承
一 基類沒有定義建構函式的情況 1 派生類也可以不定義建構函式,全部採用預設的建構函式,此時,派生類新增成員的初始化工作可以用其他公有函式來完成。2 如果只有派生類定義建構函式,只需要構造派生類物件即可,物件的基類部分使用預設建構函式來自動建立 二 基類中存在建構函式 1 基類中存在不帶引數的建構函...
C 繼承建構函式和委派建構函式
如果我們在構造b的時候想要擁有a這樣的構造方法的話,就必須乙個乙個的透傳各個介面,那麼這是很麻煩的derived int va base va derived char c base c 改寫成這樣 使用繼承建構函式 using base1 base1 而且,更神奇的是,c 11標準繼承建構函式被設...
C 建構函式的繼承問題
一 基類沒有定義建構函式的情況 1 派生類也可以不定義建構函式,全部採用預設的建構函式,此時,派生類新增成員的初始化工作可以用其他公有函式來完成。2 如果只有派生類定義建構函式,只需要構造派生類物件即可,物件的基類部分使用預設建構函式來自動建立 二 基類中存在建構函式 1 基類中存在不帶引數的建構函...