2016-07-22 249 views
0

有人能解釋爲什麼我不能在構造函數的主體中初始化一個變量,就像我可以在成員初始化列表中一樣。在類構造函數中初始化成員

class MyClass 
{ 
    public: 
    MyClass(); 
    virtual ~MyClass(void); 
    private: 
    std::string test; 
}; 

MyClass::MyClass() 
: test("asdf") <-- Case 1: This is OK 
{ 
    test("asdf"); <-- Case 2: This is not 
} 

我在問我有一個第三方類,我需要使用並通過將某些變量傳遞給它的構造函數進行初始化。如果我按照上面的情況1使用它,但沒有在情況2中使用它,那很好。

+3

你不能調用'test'作爲一個函數。 –

回答

8

語法在constructing an object in the member initialisation list之間變化,並在構造函數的主體中爲其賦值。

在初始化列表中,它是你所擁有的;

MyClass::MyClass() 
:test("abcd") 
{ 
    //... 
} 

在身上,你可以使用賦值語法

test = "abcd"; 

語法test("asdf");被解析爲一個名爲test函數被調用的"abcd"一個說法。

必須記住,如果成員沒有默認構造函數,則初始化列表是唯一正確構造成員的地方。一旦構造函數的主體運行,所有成員都以某種方式構建或初始化。如有可能(如不適用於參考和const成員等),他們可能會被分配到,但不會被重新構建。

+1

初始化列表的另一個不錯的屬性是它允許初始化const成員,*按照定義*你不能改變。 –

+0

我會說「他們可能被分配到」,因爲他們中的一些不能被分配,只有初始化,例如參考。 – Slava

1

test(「asdf」)是一個函數調用,您不能調用那樣的字符串。初始化列表(「案例1」)是一個特例。

在構造體,只是使用分配

test="asdf". 

在這種情況下,在第一串測試是默認構造(變空),然後一個新的字符串被構造和分配給構件測試。

+2

從技術上講,由於字符串獲取默認構造,因此不會進行初始化。它是在ctor體內分配的。 – NathanOliver

+0

同意。改變了我的回答 –

+0

仍然聽起來錯了「如果你想初始化然後分配」,不,你不能這樣初始化。雖然在這種情況下,結果在很多情況下都是相似的,但僅僅因爲無法以這種方式進行初始化而無法正常工作。 – Slava

1

你有波紋管方式的構造函數初始化變量:

class MyClass 
{ 
public: 
    MyClass(); 
    virtual ~MyClass(void); 
private: 
    std::string test; 
}; 

方式1:

MyClass::MyClass() : test("asdf") 
{ 
} 

方式2:

MyClass::MyClass() 
{ 
    test = "asdf"; 
} 
+1

從技術上講,這不是初始化,因爲字符串在進入ctor主體之前獲得構造函數構造的默認值。它是在ctor體內分配的。 – NathanOliver

+0

@NathanOliver是的,字符串是一個類,並在它自我構造函數初始化。 –

+0

'test =「asdf」;'不是初始化。當因爲不使用成員初始化列表而調用構造函數時,字符串成員是默認構造的。然後在ctor主體中,你要分配任務,而不是初始化。只有你的第一種方法實際上用''test'初始化變量' – NathanOliver

4

不能初始化變量在t他是構造函數的主體,因爲構造函數的主體運行在所有基類和成員已經在成員初始化列表中初始化了已經。它們隱含地默認初始化,因爲你沒有列出它們是無關緊要的。

因此,在正文中,test("asdf");試圖撥打operator()test,這會失敗。使用賦值(test = "asdf";)更改其值,或者更好地直接在成員初始化列表中初始化它。

0

你不能在構造函數體中初始化成員,因爲它已經在那個時候初始化了,並且語法反映了這個事實。這已經回答了,但我想指出另一件事 - 不正確地使用術語可能會導致錯誤的代碼。所以有人說「你可以通過賦值在構造函數體中初始化」。爲什麼這是錯的?讓我們來看看這個例子:

struct foo { 
    int i = 0; 
    int &r = i; 

    foo() {} 
    foo(int &ref); 
}; 

,你想r點一樣ref如果構造函數被調用:

foo::foo(int &ref) : r(ref) 
{ 
} 

現在,如果你嘗試通過轉讓「初始化」會發生什麼:

foo::foo(int &ref) 
{ 
    r = ref; 
} 
現在

所以不是指向相同參考 as ref您剛分配給成員i的值。這可能會導致難以發現的錯誤和士氣是:「術語在編程中很重要,你不應該自由地玩它」

相關問題