2010-09-21 70 views
0

我的代碼不能編譯。下面是我的代碼初始化模板類的成員時出現的問題

template <typename T> 

class TemplateClass 
{ 

    const T constMember; 
    public: 

    TemplateClass() 
    { 
     constMember = T(); 
    } 

}; 

int main() 
{ 
    TemplateClass <int> obj; 
} 

我得到這個錯誤:

error: uninitialized member 'TemplateClass<int>::constMember' with 'const' type 'const int'

我以爲構造函數用於初始化數據成員。怎麼了????

+1

@ user242265:你的問題與模板無關,順便說一句。 – wilx 2010-09-21 14:36:12

回答

11

你不初始化const成員,你只是分配給它。

成員初始化can only be done using a member initialization list

例如:

TemplateClass() : constMember(T()) //initializes constMember to 0 
{} 
+0

我會說'只能'而不是應該。 「只能使用成員初始化列表完成成員的初始化。」 – frag 2010-09-21 14:51:35

+1

@frag:對,編輯我的答案。 – 2010-09-21 14:52:46

+0

很好的答案,來自我的「+ 1」。但是,我覺得有必要在這個主題上再多說幾句話。 ':)' – sbi 2010-09-21 19:07:00

4

Prasoon已經給你a very good answer。但是,我想提出一個額外的觀點,我無法設法注入一條評論:

我已經看到了這個錯誤(忽略初始化列表),它被來自語言的C++新手(Java,C#),其中所有類型都是基元或引用。默認情況下,對null的複雜類型的引用進行初始化並沒有什麼不妥,然後用真實對象覆蓋它。然而,在C++中,類型具有價值語義,除非明確選擇(並實現)參考語義。

想想你的T是一個昂貴的初始化類型。 (對於「昂貴」的任何定義,如果您在想象這種類型時遇到困難,可以想象我們正在談論顯卡驅動程序的代碼,幾乎所有代碼都是昂貴的。)由於您可以自由訪問構造函數的正文需要在構造函數的正文執行時被構造。否則,你會訪問原始內存而不是有效的對象。 (構造就是將一塊原始內存變成一個有效的對象)。

所以,當你在構造函數的正文中爲對象指定了某些東西時,就是指定給已經完全構造的對象。由於您沒有指定構造函數,因此該對象將使用其默認構造函數構造。這意味着對象將首先被默認構造,只是爲了讓其默認值在下一時刻被其他的東西覆蓋。

這無疑是無稽之談,這就是爲什麼我們有初始化列表。使用它們,我們可以指定編譯器應該使用哪些構造函數來構造基類和成員子對象。這樣,立即用正確的值創建對象。另外,正如你所發現的,初始化列表是初始化某些數據成員(即常量對象,引用和沒有可訪問的默認構造函數的類型的對象)的唯一方法。