无法初始化初始化列表之外的字段

Can't initialize field outside initializer list

我遇到了一些看起来很容易的事情,所以我一定是忽略了什么。

我需要构建一个 class,它有一个也是 class(非 POD)的字段。该字段的 class 有一个默认构造函数和一个 "real" 构造函数。问题是我真的不能在初始化列表中构造字段,因为实际上构造函数有一个参数,它是一个向量,需要一个有点复杂的 for 循环来填充。

这是重现问题的最小示例。

ConstructorsTest.h:

class SomeProperty {
public:
    SomeProperty(int param1); //Ordinary constructor.
    SomeProperty();           //Default constructor.
    int param1;
};

class ConstructorsTest {
    ConstructorsTest();
    SomeProperty the_property;
};

ConstructorsTest.cpp:

#include "ConstructorsTest.h"

ConstructorsTest::ConstructorsTest() {
    the_property(4);
}

SomeProperty::SomeProperty(int param1) : param1(param1) {}
SomeProperty::SomeProperty() : param1(0) {} //Default constructor, doesn't matter.

但这给出了一个编译错误:

ConstructorsTest.cpp: In constructor 'ConstructorsTest::ConstructorsTest()':
ConstructorsTest.cpp:4:19: error: no match for call to '(SomeProperty) (int)'
    the_property(4);
                  ^

它没有像往常那样给出建议,可以代替预期的功能。

在上面的例子中我只是在初始化列表中初始化the_property,但实际上4实际上是一个复杂的向量,需要先生成,所以我真的不能.将 the_property(4) 移动到初始化列表会导致编译成功。

其他类似的线程提到该对象必须有一个 default constructor, or that it can't be const。这两个要求似乎都已满足,这里。

您不能在构造函数体内初始化数据成员。 (the_property(4); 只是试图将 the_property 作为仿函数调用。)您只能像这样分配它们:

ConstructorsTest::ConstructorsTest() {
    the_property = ...;
}

but in reality the 4 is actually a complex vector that needs to be generated first

您可以添加一个生成必要数据的成员函数,并用它来初始化member initializer list中的数据成员。例如

class ConstructorsTest {
    ...
    static int generateData();
};

int ConstructorsTest::generateData() {
    return ...;
}

ConstructorsTest::ConstructorsTest() : the_property(generateData()) {
}

你不能初始化一个变量两次1当你的构造函数启动时,all成员子对象将被构造。如果在构造函数中没有提供成员初始值设定项,或者在 class 定义中没有提供默认成员初始值设定项,那么它将执行默认初始化。不管是什么形式,都不能再构造。

复杂的多语句初始化最好通过 lambda 函数完成:

ConstructorsTest::ConstructorsTest()
  : the_property( []{ /* Do Complex Initialization */}() )
{
}

1:好吧……你可以,但不是那样。对于像这样简单的情况,你真的不应该这样做。