std :: vector <bar>作为Foo类中的成员变量需要Bar </bar>的空构造函数

时间:2013-03-24 09:57:15

标签: c++ class vector enums nested-class

情况如下:

我有一个由以下文件定义的类。

Foo.h文件:

template<typename MyType>
class Foo
{
public:
    Foo(int number = 50);

private:
    typedef enum {VAR1, VAR2} Type;

    class Bar
    {
        MyType a;
        Type b;

        Bar(int param1, Type param2) : a(param1), b(param2) {}
    }

    std::vector<Bar> vec;
};

Foo.cpp文件:

template<typename MyType>
Foo::Foo(int number) : vec(number)
{ }

问题是当我编译它时,我在.cpp文件的第一行中收到错误,说它需要一个没有参数的Bar的构造函数。我想它需要它在Foo中创建矢量。我为Bar添加了一个没有参数的构造函数,给出了以下.h文件:

template<typename MyType>
class Foo
{
public:
    Foo(int number = 50);

private:
    typedef enum {VAR1, VAR2} Type;

    class Bar
    {
        MyType a;
        Type b;

        Bar() {}   // <----  Line added
        Bar(int param1, Type param2) : a(param1), b(param2) {}
    }

    std::vector<Bar> vec;
};

现在我可以编译并且它可以正常工作,但是我刚刚添加的一行警告Member 'b' was no initialized in this constructor。枚举问题,也许?

我不明白我应该怎么做才能让它在没有这个警告的情况下工作。

编辑:我收到了一些答案,说要向空构造函数添加初始化列表。但是,我的类实际上是一个模板类,a对我来说是一个未知的类型,所以我不能初始化它,因为我不知道它的类型。我尝试在Bar的初始化列表中仅初始化b并且它有效。警告消失了,但让a未初始化是否可以?是否有一种方法可以删除没有Bar参数的构造函数,并且仍然在Foo的构造函数中给出向量的大小?

2 个答案:

答案 0 :(得分:6)

问题是Foo::Foo(int)定义中的初始化列表。你在写

Foo::Foo(int n)
    : vec(n) { }

即。你正在使用构造函数

std::vector<Bar>::vector(size_t number, const Bar &x = Bar())

请注意x = Bar(),这意味着您使用标准构造的Bar实例填充向量。由于Bar中至少定义了一个构造函数,编译器不会自动提供标准构造函数。

Bar中定义一个标准构造函数,就像其他答案一样,或者在Foo的构造函数中添加其他内容,例如

Foo::Foo(int n)
    : vec(n, Bar(1, VAR1)) { }

并且编译器错误消失。

回答您的修改:您收到的警告可能表示:成员a未正确初始化。因为它是int这可能没问题(C ++不会强迫你初始化int)。但请注意程序中稍后成员a中的奇怪和任意值。一个更好的解决方案是将它在施工时设置为一个良好的定义状态,这意味着“这个值是未知的。”

编辑:我删除了我写的有关异构容器的所有内容。但是,如果您需要这些内容,请查看我的帖子的编辑历史记录。

您可以在a的标准构造函数中初始化Bar,如下所示:

Bar::Bar() : a(MyType()), b(UNKNOWN) { }

并将UNKNOWN添加到枚举Type。这假设类型MyType是标准可构造的。这适用于所有原始类型,例如intdouble等。这为您提供了一个明确定义的Bar对象状态,这可能对您意味着 unknown 。可以通过将bUNKNOWN进行比较来测试它。

正如yakk在他的评论中所述:枚举的原始类型可以保留为单元化,但在您的情况下,编译器会警告您:可能是您的成员b包含的值没有像VAR1这样的标签或者VAR2。使用明确定义的值初始化所有成员总是一个好主意,除非你真的被迫不这样做 - 例如,如果执行是血腥的关键。

答案 1 :(得分:0)

您需要向空构造函数添加初始化列表(并可能将其公开)。

class Bar
{
    int a;
    Type b;

    Bar() : a(0), b(VAR1) {}   // initialize the members to default values.
    Bar(int param1, Type param2) : a(param1), b(param2) {}
}