如果我没有在struct中定义构造函数,我可以通过选择一个特定的值来初始化它,像这样:
struct Foo {
int x, y;
};
Foo foo = {.y = 1};
但是如果我添加新的默认构造函数,那么我就失去了这个特性:
struct Bar {
int x, y;
Bar(int value) : x(value), y(value) {}
};
Bar bar1 = 1;
Bar bar2 = {.y = 2}; // error: a designator cannot be used with a non-aggregate type "Bar"
有可能两者兼得吗?
我尝试添加默认构造函数Bar () {}
,但它似乎也不起作用。
鱼和熊掌不可兼得。如果对象有构造函数,它就不再是聚合,并且只有聚合可以用指定的初始化器初始化。你不能使用构造函数来任意初始化聚合逻辑。
我们干杯了吗?不,因为有命名构造函数习语。它本质上只是一个静态成员函数,返回一个初始化的对象,并能够执行一些逻辑。此习语与聚合初始化兼容。
struct Foo {
int x, y;
static Foo filled_with(int value) {
return {.x = value, .y = value};
}
};
Foo foo = {.y = 1}; // Still an aggregate.
Foo foo2 = Foo::filled_with(2); // Custom logic
甚至没有任何复制或移动,因为c++ 17删除了这些可能性。foo2
直接初始化
与ellipticaldoor写的类似:
struct FooBase {
int x = 0, y = 0;
};
struct Foo : FooBase {
Foo(int x_) : FooBase{.x = x_} { }
Foo(FooBase &&t) : FooBase{t} {}
};
Foo foo = {{.y = 1}};
Foo foo2{1};
到目前为止,这是我能找到的最接近的东西:
struct Vec2 {
int x, y;
};
struct Bar {
int x, y;
Bar(int value) : x(value), y(value) {}
Bar(Vec2 value) : x(value.x), y(value.y){};
};
Bar bar1 = 1;
Bar bar2 = {{.y = 2}};
但是需要使用双参数
您可以使用数据成员初始化器,使类型保持聚合:
struct Foo {
int x = 0, y = x;
};
Foo foo1 = {.y = 6}; // Foo{0, 6}
Foo foo2{7}; // Foo{7, 7}
(虽然不能从int
隐式构造)