2013-03-24 60 views
2

這裏的情況是:的std ::矢量<Bar>在Foo類的成員變量需要一個空的構造函數酒吧

我有以下文件中定義的類。

了foo.h文件:

template<typename MyType> 
class Foo 
{ 
public: 
    Foo(int number = 50); 

private: 
    typedef enum {VAR1, VAR2} Type; 

    class Bar 
    { 
     MyType a; 
     Type b; 

     Bar(int param1, Type param2) : a(param1), b(param2) {} 
    } 

    std::vector<Bar> vec; 
}; 

Foo.cpp中的文件:

template<typename MyType> 
Foo::Foo(int number) : vec(number) 
{ } 

問題是,當我編譯,我得到的.cpp文件的第一行一個錯誤,指出它需要一個沒有參數的Bar的構造函數。我想它需要它來創建Foo中的矢量。我添加了一個構造函數不帶參數的酒吧給以下.h文件中:

template<typename MyType> 
class Foo 
{ 
public: 
    Foo(int number = 50); 

private: 
    typedef enum {VAR1, VAR2} Type; 

    class Bar 
    { 
     MyType a; 
     Type b; 

     Bar() {} // <---- Line added 
     Bar(int param1, Type param2) : a(param1), b(param2) {} 
    } 

    std::vector<Bar> vec; 
}; 

現在我可以編譯和它的作品,但在該行警告我只是說說Member 'b' was no initialized in this constructor。問題與枚舉,也許?

我不明白我應該怎麼做才能讓它在沒有這個警告的情況下工作。

編輯:我收到了一些答案,說要添加一個初始化列表到空的構造函數。然而,我的班級實際上是一個模板班,a對我來說是一個未知的類型,所以我不能初始化它,因爲我不知道它的類型。我嘗試初始化Bar中的初始化列表中的b,它工作正常。警告消失了,但是可以讓a未初始化嗎?有沒有辦法刪除沒有Bar參數的構造函數,並仍然給Foo的構造函數中的向量賦予一個大小?

+0

原始類型,例如'int'和'enum',默認情況下未初始化。非原始類型,比如'struct foo {int a;}'有它們的空構造函數調用(在上面的'foo'中,隱式空構造函數什麼都不做,因爲'int'是一個基本類型,默認情況下保持未初始化。警告是說你有一個原始類型的實例,它沒有被你的構造函數初始化。如果'a'不是原始類型,'Bar():b(VAR1){}'等價於Bar():a(),b(VAR1){}' - 如果它是基本類型,那麼它是未初始化的。總之,使用'Bar():a(),b(VAR1){}' – Yakk 2013-03-24 10:59:39

回答

0

您需要將一個初始化列表添加到空的構造函數中(並且可能會公開)。

class Bar 
{ 
    int a; 
    Type b; 

    Bar() : a(0), b(VAR1) {} // initialize the members to default values. 
    Bar(int param1, Type param2) : a(param1), b(param2) {} 
} 
6

問題是在Foo::Foo(int)的定義中的初始值設定項列表。你即你正在使用的構造

std::vector<Bar>::vector(size_t number, const Bar &x = Bar()) 

請注意書寫

Foo::Foo(int n) 
    : vec(n) { } 

x = Bar()這意味着您填寫的載體與Bar標準建設的情況。由於在Bar中至少定義了一個構造函數,因此編譯器不會自動提供標準構造函數。

定義一個標準的構造函數Bar像其他答案建議或放別的東西在Foo的構造函數,例如這個

Foo::Foo(int n) 
    : vec(n, Bar(1, VAR1)) { } 

和編譯器錯誤消失。

回答您的編輯:您收到的警告可能表示:成員a未正確初始化。由於這是一個int這可能是好的(C++不會強制你初始化int s)。但請注意稍後在程序中的成員a中的奇怪和任意值。一個更好的解決方法是在施工時將其設置爲一個良好的定義狀態,這意味着你「這個值是未知的。」

編輯:我刪除了所有關於異構容器的東西。但是,如果你需要這些東西,看看我的文章的編輯歷史。

您可以在Bar這樣的標準構造函數初始化a

Bar::Bar() : a(MyType()), b(UNKNOWN) { } 

,並通過添加UNKNOWN來枚舉Type。這假定類型MyType是標準可構造的。這適用於所有基本類型,如int,double等。這給你一個明確的Bar對象的狀態,這可能意味着你未知。它可以通過比較bUNKNOWN進行測試。

由於yakk在他的評論中指出:原始類型,如枚舉可以保留未初始化,但在你的情況下,編譯警告你:這可能是你的會員b包含有像VAR1VAR2根本沒有標籤的值。除非你真的被迫不這樣做,否則初始化所有成員都是一個好主意,例如,如果執行是血腥的關鍵。

+0

我編輯了我的問題。我不能像你在答案中那樣給出'a'的值,因爲這對我來說是一種未知的類型。 – Gradient 2013-03-24 10:10:10

+0

應該指出,任何'.resize()'請求都需要類似的邏輯。如果像這樣的活動經常出現,OP可能會更好,只需在Bar中定義參數化構造函數的默認值:Bar(int param1 = 1,Type param2 = VAR1):a(param1),b(param2 ){}' – WhozCraig 2013-03-24 10:10:27

+0

@Gradient:你的意思是在構建'Foo'時,你不知道'Bar'中'a'的conrete值?在這種情況下,我建議通過將其設置爲特定值(如'0')來在內部處理'Bar'中的這種未知狀態。這可以通過'Bar'的標準構造函數完成。 – phlipsy 2013-03-24 10:13:10

相關問題