如果在C++中不需要构造函数或析构函数,是否有必要显式声明它?


#include <iostream>
class Base {
private:
std::string hello{ "hello world!" };
public:
Base()             = default;
virtual ~Base()    = default;
const std::string &getHello() const {
return hello;
}
void setHello(const std::string &hello) {
Base::hello = hello;
}
};
class Derived : public Base {
public:
Derived()                = default;
~Derived() override      = default;
};
int main(int argc, const char *argv[]) {
Derived d;
std::cout << d.getHello() << std::endl;
}

Base 和 Derived 都使用默认的构造函数和析构函数,我显式声明它们并标记为默认值。但实际上,如果你不显式声明它们,代码仍然可以很好地工作。

我的困惑是我是否需要明确声明它们。我听到了两种不同的论点,有些人认为无论你是否使用它们,你都应该声明它们,另一些人认为如果你需要一个,你声明它,否则你不需要。

那么什么是好的做法呢?

答案是(技术上(是否定的,你不需要显式声明任何特殊成员函数 - 只要你不声明任何其他特殊成员函数,这些特殊成员函数会导致抑制你可能想要(或需要(的其他特殊成员函数。

关于根据你自己声明哪些特殊成员函数隐式声明的规则在所有考虑的事情上都相当复杂 - 这个答案有一个方便的表格来说明它们。除非你想背诵这一点,否则你可能希望在所有情况下都明确。即使你确实熟记了规则,阅读你的代码的其他人也可能不知道。 核心准则 C.21 提供了更多示例,并深入探讨了为什么要这样做。

但是,虽然该指南仅建议定义或默认其余的特殊成员函数(如果您定义了其中任何一个(,但我想鼓励您始终显式默认/删除所有这些函数。我有两个原因:

  1. 它使您的意图显而易见。

  2. 它可以防止以后出现任何令人讨厌的意外。例如,如果您没有显式声明特殊成员函数,并且后来发现您需要一个自定义复制构造函数,那么您必须记住声明移动操作(如果您还没有声明( - 否则使用这些操作的所有代码都将中断,并且可能不会立即明显为什么。

此外,这与你的问题没有直接关系,但是在谈论特殊成员函数时,提醒人们三、五和零的规则总是有用的。

所以总结一下 - 你不必,但你可能应该

最新更新