2017-07-19 88 views
1

據我所知,要在類中初始化引用成員變量我必須使用初始化列表使用參數化構造函數來初始化成員變量。 另外我明白,沒有必要的默認構造函數。引用成員變量初始化錯誤與默認的構造函數

問:

  1. ,但我不明白的是,爲什麼定義了默認的構造函數拋出編譯錯誤? 編譯器是否足夠聰明以在下列情況下考慮參數化構造函數而不是拋出錯誤?

  2. 如果所有上述問題都有令人信服的答案,那麼爲什麼編譯器允許聲明默認構造函數(沒有定義)?它在這裏有什麼不同?

class SomeClass 
{ 
public: 
    //SomeClass(){} //THIS IS AN ISSUE 
    //SomeClass(); //THIS IS FINE THOUGH 


    SomeClass(int j):i(j){} 
    int& i; 

}; 
int main() 
{ 

    SomeClass obj(2); 
    return 0; 
} 

我相信同樣是const成員函數過的行爲。引用和const成員變量的原因是否相同?

+0

你也可能想重新考慮擁有一個引用成員 - 這很少是一個好主意。 –

回答

3

why defining a default constructor throws compilation error?

這不是您定義的默認構造函數,它的默認構造函數的定義不初始化i。您需要需要才能初始化所有引用的成員變量,而您的空白定義不會這樣做。

這是你需要初始化引用變量一樣的道理:

void foo() { 
    int &i; // error: declaration of reference variable 'i' requires an initializer 
} 

why would the compiler allow declaration of default constructor(without definition)

因爲定義是問題,而不是申報。例如,移動病態的構造函數定義的類定義之外將產生同樣的錯誤:

class SomeClass 
{ 
public: 
    SomeClass(); 
    int &i; 
}; 

SomeClass::SomeClass() {} // error: constructor for 'SomeClass' must explicitly initialize the reference member 'i' 

唯一的問題與這兩個例子是,你沒有初始化i

注意下列將編譯的例子。請注意,構造函數的聲明不會更改,但定義會初始化i

int someGlobalInt; 

class SomeClass 
{ 
public: 
    SomeClass() : i(someGlobalInt) {} 
    int &i; 
}; 

int someGlobalInt; 

class SomeClass 
{ 
public: 
    SomeClass(); 
    int &i; 
}; 

SomeClass::SomeClass() : i(someGlobalInt) {} 
+0

嗯,問題更多:_當我已經提供了一種方式來初始化通過參數化構造函數的成員變量,那麼爲什麼尋找默認構造函數?此外,在參數化構造函數的存在下,如果不允許定義默認構造函數,那麼爲什麼還應該允許默認構造函數的聲明呢? _ – anurag86

+0

@ anurag86 *「在參數化構造函數存在的情況下,如果不允許使用默認構造函數的定義」* - 允許使用默認構造函數**的定義**,您剛提供了一個不合格的定義,因爲它沒有' t初始化'我'。 **如果完全刪除參數化的構造函數,將會遇到相同的錯誤。** – cdhowie

+0

明白了。謝謝。 – anurag86

1

編譯器要求對所有引用進行初始化。如果你定義了一個默認的構造函數,那麼編譯器會抱怨,因爲你沒有初始化i。如果你聲明瞭默認構造函數,那麼你還沒有定義它,所以編譯器沒有問題。考慮這個:

class SomeClass 
{ 
    SomeClass(); // Compiler is fine with this 
    ... 
}; 

int someInt; 
SomeClass::SomeClass(): i(someInt) {} // OK - i is initialized 

您以後定義了構造函數並初始化了i

+0

如果是這樣,爲什麼甚至會允許一個聲明? – anurag86

+0

@ anurag86爲什麼不呢?您稍後可能想要派生'SomeClass'並使用調用基類的默認ctor的自定義初始化程序列表。 – George

+0

@ anurag86,因爲編譯器只關心定義。它不知道你是否將初始化引用時,它只是聲明 – Kevin

0

首先是其失敗的基準部件的所要求的初始化一個構造的實施方案:
SomeClass(){}

第二種是僅一個構造的聲明。只要它沒有得到執行,缺乏實施就不成問題。和,只要它不實現的(可能的)未初始化是沒有問題的:
SomeClass();

注意,非參數化的構造能正確初始化的基準構件,例如引用全局變量或靜態變量。這可能對任何事情都沒有用處,但這是可能的。所以對於編譯器來說,第二個版本不是直接的問題,並不一定表示其他地方的實際問題。

相關問題