我正在准备我的CPP考试,其中一个问题是:你能删除默认的类构造函数吗?如果是,那么这样做的原因是什么?好的,显然你可以做到:
class MyClass
{
public:
MyClass() = delete;
};
但我不明白你为什么要这样做?
答案 0 :(得分:72)
考虑以下课程:
struct Foo {
int i;
};
此类是聚合,您可以使用以下所有三个定义创建实例:
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
仍然是聚合,但只有后两个定义有效 - 第一个定义现在是编译时错误。
答案 1 :(得分:45)
删除默认构造函数有几个原因。
= delete
是样式的东西,正如@HolyBlackCat所说的那样,但它通过告诉客户端代码仅使用参数调用构造函数来澄清你的意图。如果第二个陈述不清楚,请考虑以下示例:
class A
{
public:
//A() = delete;
A(int, int) {};
};
如果您现在尝试调用默认构造函数,则会出现类似的错误(GCC 7.2):
错误:没有匹配函数来调用' A :: A()'
但是,如果您使用= delete
取消注释该行,那么您将获得以下内容:
错误:使用已删除的功能' A :: A()'
这明确表明,人们试图使用已删除的构造函数与其他错误进行比较,这有点不清楚。
答案 2 :(得分:5)
多个默认选项
当默认或未初始化状态有多个选项时,删除类的默认构造函数是个好主意。例如,假设我有一个班级,
template<typename F>
class Polynomial;
表示字段上的多项式F
。在这种情况下,多项式的默认值有很多选择。一个可以是加法下的多项式的同一性,即零,但我们也可以具有乘法同一性,即单位。这取决于用户打算如何推断该类以及如何使用它。
无默认选择
另一个值得注意的情况是,当我们没有任何可能有意义的多个默认状态时。例如,假设我们有一个表示歧管或表面的类。
那么Manifold()
是什么?它是一个空的空间,没有任何东西,没有表面,没有距离或公制的概念。但是,将它看作是一种流形并不是有意义的,而是像拓扑空间那样更通用的东西。
因此,在这种情况下,我也会选择删除默认构造函数。
答案 3 :(得分:5)
有时候不打算对类进行实例化。
到目前为止尚未提及的一个例子是“特质”类。
例如,考虑std::char_traits
,虽然标准没有说它的默认构造函数需要删除,但它的默认构造函数没用,因为类本身是空的,它的所有函数都是静态的,它不是需要实例化以使用它提供的类型别名。
Trait类通常只用于支持其他类(通常是其他模板类),因此删除它们的默认构造函数通常是有意义的 - 强化它们只是一个帮助器类型而不是真的应该这样的概念像对象一样使用。