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

std::vector<Bar> as a member variable in class Foo needs an empty constructor for Bar

本文关键字:一个 构造函数 变量 gt Bar lt vector std Foo 成员      更新时间:2023-10-16

情况如下:

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

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。enum有问题吗?

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

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

问题在于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 s),但要注意稍后程序中成员a中的奇怪和任意值。更好的解决方案是在构建时将其设置为定义良好的状态,这意味着"此值是未知的"。

Edit:我删除了我写的所有关于异构容器的东西。但是,如果你需要这些东西,可以看看我的帖子的编辑历史。

你可以在Bar的标准构造函数中初始化a,像这样:

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

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

正如yakk在他的评论中所说:像枚举这样的基本类型可以保持初始化,但在你的情况下,编译器警告你:可能是你的成员b包含一个值,而VAR1VAR2根本没有标签。用定义良好的值初始化所有成员总是一个好主意,除非你真的被迫不这样做——例如,如果执行是非常重要的。

您需要在空构造函数中添加一个初始化列表(并且可能将其设为public)。

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) {}
}
相关文章: