構造方法用來初始化類的對象,與父類的其它成員不同,它不能被子類繼承(子類可以繼承父類所有的成員變量和成員方法,但不繼承父類的構造方法)。因此,在創建子類對象時,為了初始化從父類繼承來的數據成員,系統需要調用其父類的構造方法。
如果沒有顯式的構造函數,編譯器會給一個默認的構造函數,並且該默認的構造函數僅僅在沒有顯式地聲明構造函數情況下創建。
構造原則如下:
1. 如果子類沒有定義構造方法,則調用父類的無參數的構造方法。
2. 如果子類定義了構造方法,不論是無參數還是帶參數,在創建子類的對象的時候,首先執行父類無參數的構造方法,然后執行自己的構造方法。
3. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數,則會調用父類的默認無參構造函數。
4. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數且父類自己提供了無參構造函數,則會調用父類自己的無參構造函數。
5. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數且父類只定義了自己的有參構造函數,則會出錯(如果父類只有有參數的構造方法,則子類必須顯示調用此帶參構造方法)。
6. 如果子類調用父類帶參數的構造方法,需要用初始化列表的方式。
結論:子類構造函數必須要調用父類的構造函數(無論顯式還是隱式),本質原因在於繼承的性質決定了必須先有父再有子!
看一個例子:在執行new A1時,下面代碼的輸出是什么
#include <iostream> using namespace std; int init(const std::string & info) { std::cout << info << std::endl; return 0; } class A { int m_x; public: A():m_x(init("Init A::m_x")) { init("Call A::A()"); } }; class A1:public A { int m_x; int m_y; public: A1(): m_y(init("Init A1::m_y")), m_x(init("Init A1::m_x"))
{
init("Call A1::A1()");
}
};
打印出來的結果為:
Init A::m_x
Call A::A() ==>是因為隱式調用了父類的構造函數
Init A1::m_x ==>按照成員變量的聲明順序“而非”初始化列表指定的順序來進行構造
Init A1::m_y
Call A1::A1()
參考:
http://www.cnblogs.com/sunada2005/p/3396585.html
http://blog.csdn.net/scottly1/article/details/25594439