当存在其他构造函数时,如何强制创建默认序列构造函数

How to force creation of default sequence constructor when other constructors are present?

本文关键字:构造函数 默认 创建 何强制 存在 其他      更新时间:2023-10-16

从C 11开始,我们拥有此出色的功能,它使我们能够避免为所有小型类创建显式构造函数:

class A
{
public:
  A() = default;
  A(int x, int y) : x(x), y(y) {} // bloat
  int x = 0, y = 0;
};
..
A a(1,2);

所以我们现在可以这样写:

class A
{
public:
  int x = 0, y = 0;
};
..
A a{1,2}; // using the sequence constructor created by the compiler, great

出现的问题是,当我还有其他要使用的构造函数时,例如:

class A
{
public:
  A() = default;
  A(Deserialiser& input) : a(input.load<int>()), b(input.load<int>()) {}
  int x = 0, y = 0;
};
...
A a{1, 2}; // It doesn't work now, as there is another constructor explicitly specified

问题是,如何强制编译器创建默认序列构造函数?

第二个示例的区别在于您正在做汇总初始化

使用第一个和第三个示例,不再可能进行汇总初始化(因为该类具有用户定义的构造函数)。

使用第一个示例,然后称为两个题目的构造函数。使用第三个示例,找不到合适的构造函数,您将遇到错误。


注意:在第二个示例中,在C 11中也无法进行汇总初始化,因为C 11不允许非静态成员被初始化。在C 14中取消了该限制。(有关更多信息,请参见上面的链接参考。)

如果命名构造函数,则删除所有其他自动生成名称。

通过命名A(Deserialiser&),您丢失了自动生成的A(int, int)

在表达构造函数的路上将是:

class A
{
public:
  A() : A(0, 0) {}   // <- set default values here
  A(int x, int y) : x(x), y(y) {}
  A(Deserialiser& input) : x(input.load<int>()), y(input.load<int>()) {}
  int x, y;
};

保留汇总初始化的一种方法是将序列化与对象本身分离。

template<class Type> struct type_tag {};
class A
{
public:
    A()  = default;
    int x = 0, y = 0;
};
auto deserialise(Deserialiser& input, type_tag<A>)
{
    return A { input.load<int>(), input.load<int>() };
}

只要您不提供任何类的构造函数,编译器自动生成默认构造函数。但是,一旦您提供了最低的构造函数,那么编译器即使没有更多默认构造函数也不会提供任何构造函数。