首先,本篇文章只講 “默認構造函數”,即如你所知,默認構造函數是不帶參數的構造函數。
編譯器會在 適當的時候 為class合成一個默認構造函數 ~~
先問以下兩個問題:
編譯器會為任何沒有聲明構造函數的class,合成默認構造函數?? 錯!!!
合成的默認構造函數會顯示設定class內的每一個data member的默認值?? 錯!!!
class Base { public: int x; int getX() const {return x;}; }; int main() { Base b; cout << b.getX() << endl; return 0; }
編譯器的動作,是僅限於自己的責任,類的設計者如果需要為類的所有成員進行初始化,那麼自己動手吧!!
編譯器的動作是隱式的,因此,了解什麼時候算是 “適當的時候”??
以下的4個方面是編譯器的所謂的適當的時候。。。
1 帶有“默認構造函數”的類成員對象。
就是說,如果類A的一個對象a作為類B的成員變量,並且類B沒有定義構造函數,但是類A有自己的默認構造函數,那麼,在定義類B的對象時,編譯器會為類B合成一個默認構造函數。因為在創建類B的對象時,期間必須調用類A的默認構造函數初始化a。
例如:
執行結果為:
可以看到,成員變量b2和b的默認構造函數被調用,並且是按照其聲明次序。
2
帶有默認構造函數的基類<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+vs3Kx8u1oaPI57n7wOBEZXJpdmVkvMyz0NfUwOBCYXNlo6y1q8rHQmFzZcDgw7vT0Lao0uXErMjPubnU7Lqvyv21xLuwo6y31sG91tbH6b/2o7o8L3A+CjxwPsjnufvV4rj2RGVyaXZlZMDgw7vT0Lao0uW5udTsuq/K/aOsxMfDtLHg0uvG97HYtqi74c6qxuS6z7PJ0ru49qOs0vLOqrTLyrG1xMSsyM+5udTsuq/K/b2rsrvKx3RyaXZpYWy1xKOs0vK0y7HY0Ou9q8v8us+zyaOs08PT2rP1yry7r7v5wOChozwvcD4KPHA+yOe5+0Rlcml2ZWTA4Lao0uXBy9fUvLqw5rG+tcS5udTsuq/K/aOs1eLG5NbQsqLDu9PQxKzIz7m51Oy6r8r9o6zEx8O01NrV4tCptqjS5bXEubnU7Lqvyv2199PD1q7HsKOsu7nKx7vhtffTw7v5wOC1xMSsyM+5udTsuq/K/aGjPC9wPgo8cD7I58/Co7o8L3A+CjxwPjwvcD4KCjxicj4KPHA+PC9wPgo8cD7WtNDQveG5+86qo7o8L3A+CjxwPjxpbWcgc3JjPQ=="http://www.2cto.com/uploadfile/Collfiles/20140514/20140514092922283.png" alt="\">
可以看到,在Derived類中並沒有默認構造函數,但是當我們使用 "以int作為參數的構造函數"時,其基類的默認構造函數被調用(按聲明次序),調用完成之後,如果還有成員對象,再調用該類的默認構造函數(如此處的Member).
3 帶有 ”虛函數“的類
也就是說,如果一個class繼承一個虛函數,或者是一個類的繼承體系中含有 virtual繼承。如果用戶沒有定義構造函數,那麼編譯器會合成。
如下: