2010-09-21 67 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是一个昂贵的初始化类型。 (对于“昂贵”的任何定义,如果您在想象这种类型时遇到困难,可以想象我们正在谈论显卡驱动程序的代码,几乎所有代码都是昂贵的。)由于您可以自由访问构造函数的正文需要在构造函数的正文执行时被构造。否则,你会访问原始内存而不是有效的对象。 (构造就是将一块原始内存变成一个有效的对象)。

所以,当你在构造函数的正文中为对象指定了某些东西时,就是指定给已经完全构造的对象。由于您没有指定构造函数,因此该对象将使用其默认构造函数构造。这意味着对象将首先被默认构造,只是为了让其默认值在下一时刻被其他的东西覆盖。

这无疑是无稽之谈,这就是为什么我们有初始化列表。使用它们,我们可以指定编译器应该使用哪些构造函数来构造基类和成员子对象。这样,立即用正确的值创建对象。另外,正如你所发现的,初始化列表是初始化某些数据成员(即常量对象,引用和没有可访问的默认构造函数的类型的对象)的唯一方法。