#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全部使用默认构造函数和析构函数,我明确声明了它们并将其标记为默认值。但是实际上,如果您未明确声明它们,则代码仍然可以很好地工作。
我的困惑是我是否需要显式声明它们。我听到了两种不同的论点,有人认为无论是否使用它们,都应该声明它们,而其他人则认为,如果需要,则可以声明它,否则就不需要。
那么什么是好习惯?
答案 0 :(得分:0)
答案是(从技术上来说)不,您不需要显式声明任何特殊成员函数-只要您不声明任何其他特殊成员函数而导致抑制您可能想要的其他特殊成员函数(或需要)。
关于所有特殊成员函数的隐式声明规则取决于您声明自己的隐式声明,所有考虑的事情都很复杂-this答案有一个方便的表格来说明它们。除非您想认真学习,否则您可能想在所有情况下都保持坦率。即使您确实知道规则,但其他人可能也不会阅读您的代码。 Core Guideline C.21提供了更多示例,并深入说明了为什么要这样做。
但是,尽管指南仅建议定义或默认其余的特殊成员函数(如果您定义了其中的任何一个),但我还是鼓励您始终明确地默认/删除所有它们。我有两个原因:
它使您的意图显而易见。
它可以防止以后出现任何令人讨厌的意外情况。如果您没有明确声明特殊的成员函数,而后又发现自己需要一个自定义的复制构造函数,那么您必须记住要声明移动操作(如果还没有的话),否则所有使用这些操作的代码都会中断,并且可能不是立即显而易见的原因。
此外,这与您的问题没有直接关系,但是在谈论特殊成员函数时,提醒人们注意rules of three, five and zero.
总是很有用的总而言之-您没有必须,但您可能应该。