我的代码无法编译。以下是我的代码
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'
我认为构造函数用于初始化数据成员。怎么了????
答案 0 :(得分:11)
您没有初始化const成员,只是分配给它。
成员初始化can only be done using a member initialization list。
例如:
TemplateClass() : constMember(T()) //initializes constMember to 0
{}
答案 1 :(得分:4)
Prasoon已经给了你a very good answer。但是,我想提出一个额外的观点,我无法将其纳入评论:
我已经看到C ++新手做了很多错误(忽略初始化列表),这些新手来自语言(Java,C#),其中所有类型都是基元或引用。默认情况下,使用null
初始化对复杂类型的引用并稍后用真实对象覆盖它并不是什么大问题。但是,在C ++中,类型具有值语义,除非明确选择(和实现)引用语义。
认为您的T
是一种昂贵的初始化类型。 (对于“昂贵”的任何定义。如果您无法想象这样的类型,请想象我们正在谈论图形卡驱动程序的代码。对于这样的代码,几乎任何东西都是昂贵的。)因为您可以自由地访问该对象构造函数的主体在执行时需要构造它的构造函数的主体。否则,您将访问原始内存而不是有效对象。 (构造就是将原始内存的blob变成一个有效的对象。)
因此,当您在构造函数体中为对象赋值时,您将分配给已经完全构造的对象。由于未指定构造函数,因此将使用其默认构造函数构造对象。这意味着该对象将首先被默认构造,只是为了让它的默认值在下一刻被其他东西覆盖。
这当然是胡说八道,这就是为什么我们有初始化列表。使用它们,我们可以向编译器指定它应该使用哪些构造函数来构造基类和成员子对象。这样,立即使用正确的值创建对象。
此外,正如您所发现的,初始化列表是初始化某些数据成员的唯一方法,即常量对象,引用和没有可访问的默认构造函数的类型的对象。