无法初始化初始化列表之外的字段
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:好吧……你可以,但不是那样。对于像这样简单的情况,你真的不应该这样做。
我遇到了一些看起来很容易的事情,所以我一定是忽略了什么。
我需要构建一个 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:好吧……你可以,但不是那样。对于像这样简单的情况,你真的不应该这样做。