删除默认 class 构造函数有什么意义?

What's the point of deleting default class constructor?

我正在准备我的 CPP 考试,其中一个问题是:您可以删除默认的 class 构造函数吗?如果可以,这样做的原因是什么?好的,显然你可以做到:

class MyClass 
{ 
  public: 
    MyClass() = delete; 
};

但我不明白你为什么要这么做?

删除默认构造函数有几个原因。

  1. class 是纯静态的,您不希望用户实例化仅具有静态 methods/members 的 class。这种 class 的一个示例可能是仅使用静态方法来创建新的 classes 来实现工厂设计模式的示例。
  2. class 没有默认构造函数(因为它要求 parameters/There 没有对 class 有意义的默认值)。在这种情况下,= delete 是一种样式,正如@HolyBlackCat 所说,但它确实通过告诉客户端代码 调用带有参数的构造函数来阐明您的意图。
  3. 您不需要聚合的未初始化数据 class。

如果第二个陈述不清楚,请考虑以下示例:

class A
{
public:
   //A() = delete; 
   A(int, int) {};
};

如果您现在尝试调用默认构造函数,您会收到类似于 (GCC 7.2):

的错误

error: no matching function for call to 'A::A()'

但是,如果您取消注释带有 = delete 的行,那么您将得到以下内容:

error: use of deleted function 'A::A()'

这清楚地表明,与另一个错误相比,一个人正在尝试使用已删除的构造函数,这有点不清楚。

考虑以下 class:

struct Foo {
    int i;
};

这个 class 是一个聚合,您可以创建一个包含所有这三个定义的实例:

int main() {
    Foo f1;     // i uninitialized
    Foo f2{};   // i initialized to zero
    Foo f3{42}; // i initialized to 42
}

现在,假设您不喜欢未初始化的值以及它们可能产生的未定义行为。您可以删除 Foo:

的默认构造函数
struct Foo {
    Foo() = delete;
    int i;
};

Foo 仍然是一个集合,但只有后两个定义有效 -- 第一个现在是编译时错误。

多个默认选择

当默认或未初始化状态有多种选择时,删除 class 的默认构造函数是个好主意。例如,假设我有一个 class,

template<typename F>
class Polynomial;

表示字段上的多项式,F。在这种情况下,多项式的默认值有多种选择。一个可以是加法下多项式的恒等式,即零,但我们也可以有乘法恒等式,单位。这取决于用户打算如何推理 class 以及如何使用它。


无默认选择

另一个值得注意的情况是,我们没有多个有意义的默认状态,而是 none。例如,假设我们有一个 class 代表一个 流形 或表面。

Manifold()是什么?它是一个空的 space,什么都没有,没有表面,没有距离或公制的概念。但是将其视为流形是没有意义的,而是可能更一般的东西,如拓扑 space.

因此,在这种情况下,我也会选择删除默认构造函数。

有时 classes 不打算被实例化。

到目前为止尚未提及的一个示例是 'trait' classes。 例如,考虑 std::char_traits,虽然标准没有说它的默认构造函数需要删除,但它的默认构造函数几乎没有用,因为 class 本身是空的,它的所有函数都是静态的并且它不需要被实例化来使用它提供的类型别名。

Trait classes 通常只用于支持其他 classes(通常是其他模板 classes),因此删除它们的默认构造函数通常是有意义的 -强化它们只是辅助类型而不应该像对象一样使用的概念。