我們常常在初始化類資料成員的時候,對使用初始化表和在建構函式中十分困惑,這二者有什麼區別呢?我們應該如何選擇呢?
先舉個簡單的例子,看下面的兩段**:
**a:
[cpp]view plain
copy
print?
inline
account::account(
const
char
* name,doubl opening_bal)
::_name(name),
_balance(opening_bal)
**b:
[cpp]view plain
copy
print?
inline
account::account(
const
char
* name,doubl opening_bal)
上述兩段**的區別是:
**a把對資料成員_name和_balance的初始化放在初始化表中,而**b是在建構函式中進行賦值操作。
上述兩段**的結果是相同的。在建構函式的結束處,三個成員都含有相同的值,區別是成員初始化表只提供該類資料成員的初始化。
尤其是要注意的是:建構函式中的對成員進行設定值是
賦值操作
,不是初始化操作,其初始化操作已經在初始化表中進行。
我們可以認為建構函式的執行過程分為兩個階段:隱式或顯式初始化階段,以及一般的計算階段。計算階段由建構函式體內的所以語句構成。
初始化階段可以是顯式的或是隱式的,取決於是否存在成員初始化表。隱式初始化階段按照宣告的順序依次呼叫所以基類的預設建構函式,然後是所有成員類物件的預設建構函式。
例如如下**:
[cpp]view plain
copy
print?
class
account;
[cpp]view plain
copy
print?
inline
account::account()
則初始化階段是隱式的。在建構函式體執行之前,先呼叫與_name相關聯的預設string建構函式,這意味著把空串賦值給_name是不必要的。
對於類物件,在初始化和賦值直接的區別是巨大的。成員類物件應該總是在成員初始化表中被初始化,而不是在建構函式體內被賦值。預設account建構函式更正確的實現如下:
[cpp]view plain
copy
print?
inline
account::account()
:_name(string())
去掉了不必要的建構函式體裡面的賦值操作。
對於預設建構函式的顯式呼叫也是不必要的,可以如下實現:
[cpp]view plain
copy
print?
inline
account::account()
:_name()
對於內建型別的資料成員,用成員初始化表和在建構函式體內初始化是相同的嗎?不。
除了兩個例外,兩個在結果和效能上都是等價的。更受歡迎的是用成員初始化表。
兩個例外是任何型別的const和引用資料成員。因為他們必須在成員初始化表中被初始化,否則會產生編譯時刻錯誤。
每個成員只能在成員初始化表中出現一次,初始化順序是由成員在類中被宣告的順序決定的,而不是由名字在初始化表中的順序決定的。但是在初始化表中出現的成員總是在建構函式體內成員的賦值之前被初始化。
2 6 建構函式與類成員的初始化
1 建構函式一大功能就是初始化成員變數 1 預設建構函式不帶參,無初始化功能 2 若無其他建構函式,則預設建構函式可以省略。但若有哪怕1個其他建構函式,則預設建構函式不能省,必須寫上。3 棧上分配物件時,若使用預設建構函式,則物件變數後面不加空的 若用帶參構造才需要加 初始化引數 2 c 的成員初始...
c 建構函式初始化類成員
includeusing namespace std class box box box int h,int w,int l int box volume int main box box int h,int w,int l hight h width w length l int box volu...
類成員初始化
在類內部 初始化的順序 靜態的成員變數 普通的成員變數 構造器的呼叫。在派生類中 初始化的順序 呼叫基類的構造器 按宣告順序呼叫成員的初始化方法 呼叫派生類構造器主體 大多數類的初始化都是按照這些順序結合在一起的。下面是乙個例子 public class test extends sub publi...