2013-03-24 63 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未在构造函数中初始化。但是,请注意,发出任何此类警告所需的编译器是而不是