2013-03-24 66 views
1

我需要一個不帶參數的默認構造函數。我怎樣才能初始化屬性爲a的未知類型。具有未知類型屬性的模板類中的默認構造函數

template <typename Type> 
class Foo 
{ 
public: 
    Foo() : a(), b(0) {} <---- Here is the confusion 

private: 
    Type a; 
    int b; 
}; 

編輯:答案已下面的評論已經給出,但仍有一些我不明白。如果我有:

typedef enum {AB, CD} EnumType 

template <typename Type> 
class Foo 
{ 
public: 
    Foo() {} // <---- "Member 'b' was no initialized in this constructor" 

private: 
    Type a; 
    EnumType b; 
}; 

我的編譯器給了我這個警告:Member 'b' was no initialized in this constructor。爲什麼它給我這個警告b這是一個枚舉而不是a

+1

只要'Type'具有默認構造函數,或者是內置的,你所做的就是正確的。 – juanchopanza 2013-03-24 21:34:30

+0

寫'a()'可以處理'int','char'等類型。 – Gradient 2013-03-24 21:35:36

+1

是的,它可以寫成'Foo():a(),b(){}' – juanchopanza 2013-03-24 21:36:29

回答

1

只要類型Type具有默認構造函數,這是正確的。當你聲明模板時你假設了一些關於類型的東西,並不是每個類型都可以在特定模板的構造函數中傳遞。在這裏,對於標準類型和那些具有默認構造函數的東西,一切都會很好。如果使用不提供默認構造函數的類型初始化類Foo,那將是一個錯誤。

回答你的第二個問題:

如果你已經在命名空間內定義您的變量,它會被初始化爲0值

enum SomeEnum { 
    EValue1 = 1, 
    EValue2 = 4, 
}; 
SomeEnum e; // e is 0 
int i;  // i is 0 

int main() 
{ 
    cout << e << " " << i; //prints 0 0 
} 

不要感到驚訝,e可以有不同的價值觀來自SomeEnum的任何枚舉值。每個枚舉類型都有一個基礎整型(例如int,shortlong),並且該枚舉類型的對象的可能值集合是基礎整型類型所具有的一組值。枚舉只是方便地命名一些值並創建一個新類型的一種方式,但是您不會通過枚舉值的集合來限制枚舉的值。

要零初始化類型T的對象是指:
- 如果T是一個標量類型(3.9),所述對象被設置爲0 (零)的值變換至T;

請注意,枚舉是標量類型。

要值初始化類型T的對象是指:
- 如果T是一個類類型 等等等等
- 如果T是一個非工會類 類型等等等等
- 如果T是一個數組型,然後等等等等 - 否則,該目的是零初始化

typedef enum {a,b,c,d} EnumType; 

template <typename Type> 
class Foo 
{ 
public: 
    Foo() {} // <---- "Member 'b' was no initialized in this constructor" 

public: 
    Type a; 
    EnumType b; 
}; 

/* 
* 
*/ 
int main(int argc, char** argv) { 

    Foo<int> fo; 
    std::cout<<std::endl<<"fo.a:"<<fo.a<<",fo.b:"<<fo.b<<std::endl; 
    EnumType e=d; 
    fo.b=d; 
    std::cout<<std::endl<<"fo.a:"<<fo.a<<",fo.b:"<<fo.b<<std::endl; 

    Foo<int>* go=new Foo<int>; 
    std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl; 
    go->b=d; 
    std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl; 

fo.a:-137090040,fo.b:32767

fo.a:-137090040,fo。B:3

中間人>一個:-166889576,中間人> B:32767

中間人>一個:-166889576,中間人> B:3-

現在

Foo<int>* go=new Foo<int>(); 
    std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl; 
    go->b=d; 
    std::cout<<std::endl<<"go->a:"<<go->a<<",go->b:"<<go->b<<std::endl; 

中間人>一個:0,中間人> b:0

中間人>一個:0,中間人> b:3-

+0

所以這個警告意味着:「因爲我沒有在Foo構造函數中初始化'b',所以它會零初始化,它可能不是你的意思,因此這個警告「。我的解釋是否正確? – Gradient 2013-03-24 22:47:02

+0

在你的例子中,a和b似乎不是零初始化的。 – Gradient 2013-03-24 22:50:22

+0

它不是。如果你在堆上創建它,它將被初始化爲零 – 4pie0 2013-03-24 22:51:23

2

我該如何初始化屬於未知類型的屬性a。

您的解決方案是正確的。根據C++ 11標準的第8.5/11段:

對象的初始值爲一組空括號,即(),應進行值初始化。 [...]

然後,第8.5/8:

要值初始化類型T的對象是指:

- 如果T是一個(可能是CV-合格)類類型(第9章),不帶默認構造函數(12.1)或 默認構造函數,用戶提供或刪除,然後對象被默認初始化;

- 如果T是沒有用戶提供或刪除的默認構造函數的(可能是cv限定的)非聯合類類型,那麼該對象是零初始化的,並且如果T具有非平凡的默認構造函數,默認初始化;

- 如果T是一個數組類型,則每個元素都進行了值初始化;

- 否則,該對象是零初始化的。

最後,

爲什麼給我這個警告,對於B是一個枚舉,而不是一個?

這可能是因爲你指定了一個模板參數Type這是一個UDT(用戶定義的類型),可以默認構造。如果情況並非如此,那麼我希望編譯器也會警告你關於a未在構造函數中初始化。但是,請注意,發出任何此類警告所需的編譯器是而不是