作者: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;
}
註:隱式定義的建構函式本身並不分配記憶體,它只是對一個類對象的初始而已,在聲明對象時分配完記憶體,建構函式才被執行。並且也不對資料成員初始化。
作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/