作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
1.什么是默認構造函數?
一個函數是默認構造函數當且僅當調用它可以不需要傳入任何參數。這個函數可以是用戶自定義的,也可以是編譯器產生的。下邊的各種構造函數都是默認構造函數。
struct A
{int x;
A(): x(0) {}};struct B: A
{//no user-defined ctor.
//the compiler implicitly declares a default constructor
};class C
{public:
explicit C(int n=0, int m=0); // may be invoked with no arguments};
2.編譯器什么時候隱式聲明默認構造函數?
有兩個條件:
- 該類沒有顯式聲明任何構造函數。--既然你都定義了,系統就不給你生成了。
- 數據成員中沒有const和reference。--因為要初始化。
滿足則隱式生成默認構造函數。這里強調“任何”,是指即使用戶自定義了復制構造函數或一個需要多個參數的構造函數,默認構造函數也不會被隱式聲明了。
所以,在定義一個類時要保證有默認的構造函數。
3.隱式聲明默認構造函數都干了什么?
什么都不做!確切的說,無論是隱式還是顯式聲明,都不意味着構造函數被定義。我們看看下邊的情況:
class B
{B(); //declaration only
};B::B() {} //separate definition of the user-declared default constructor
class C
{C() {} //declaration and definition
};class D
{//implicit declaration of a default constructor, no implicit definition
};class E
{//implicit declaration + implicit definition of a default constructor
virtual void f();};class F
{virtual void f();public:
F(); ////explicit declaration a default constructor, user forgot a definition
};
最后一種情況是常見的錯誤,用戶忘記定義這個顯式聲明的默認構造函數,這會導致鏈接錯誤——用戶自定義的默認構造函數必須實現,哪怕是空實現。
我們注意到class D的情況隱式聲明,但是沒有隱式定義,既然沒有隱式定義,那編譯器何必隱式聲明呢?
首先我們要進一步明確隱式聲明和隱式定義的實質,這兩個動作都是概念上的,編譯器並非真的到你的頭文件中插入了相關代碼,只是編譯器、連接器和程序的行為表現出好像進行了這樣的動作。實際上,編譯器就是設置了幾個bit做了標識而已。之所以要進行隱式聲明,編譯器只是規定了一個類可以被如何使用(Each implicit declaration is like an article in a contract that states how a certain class may be used. When the compiler implicitly declares one of the special member functions, it grants certain authorizations to the user.)
4.什么時候編譯器隱式定義一個隱式聲明的默認構造函數?
在下列情況中的任何一種就會隱式定義:
- 帶有虛擬成員函數的類——完成vptr的初始化。
- 子類——隱式執行基類默認構造函數。
#include using namespace std;class Bar
{public:
Bar(){cout<< "Default constructor!"<< pre> };class Too:public Bar{};//Foo::Foo(Bar bar):bar(bar){}
int main()
{Too too1;return 0;
}
- 虛擬基類繼承。
注:隱式定義的構造函數本身並不分配內存,它只是對一個類對象的初始而已,在聲明對象時分配完內存,構造函數才被執行。並且也不對數據成員初始化。