2

这是情况:

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

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对我来说是一个未知类型,所以我无法初始化它,因为我不知道它的类型。我尝试仅b在 Bar 的初始化列表中进行初始化,它起作用了。警告消失了,但是让a未初始化可以吗?有没有办法删除没有 Bar 参数的构造函数,并且仍然给 Foo 构造函数中的向量一个大小?

4

2 回答 2

6

The problem is the initializer list in the definition of Foo::Foo(int). You're writing

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

i.e. you're using the constructor

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

Please note that x = Bar() which means you fill the vector with standard constructed instances of Bar. Since there's at least one constructor defined in Bar the compiler does not automatically provide the standard constructor.

Define a standard constructor in Bar like the other answers suggest or put something else in the constructor of Foo, for example this

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

and the compiler error vanishes.

Answer to your edit: The warning you receive probably means: The member a isn't proper initialized. Since it's an int this might be okay (C++ does not force you to initialize ints). But beware of strange and arbitrary values in the member a later in your program. A better solution is to set it at construction time to a well-defind state which means to you "this value is unknown."

Edit: I deleted all the stuff I wrote about heterogeneous containers. However if you need these things take a look at the edit history of my post.

You can initialize a in the standard constructor of Bar like this:

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

and by adding UNKNOWN to the enumeration Type. This assumes the type MyType is standard constructible. This applies for example to all primitive type like int, double, etc. This gives you a well defined state of the Bar object which could mean to you unknown. It can be tested by comparing b to UNKNOWN.

As yakk stated in his comment: Primitive types like enumerations can be left unitialized but in your case the compiler warns you: It may be your member b contains a value which has no label like VAR1 or VAR2 at all. It is always a good idea to initialize all members with well-defined values unless you're really forced to not to do so - for example if execution is bloody crucial.

于 2013-03-24T10:04:05.627 回答
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) {}
}
于 2013-03-24T10:00:52.093 回答