我无法理解自动添加默认ctors背后的基本原理。特别是我觉得非常尴尬,每次我只需要添加一个空的虚拟析构函数,仅此而已,我放松了移动的东西,但添加它们我松散副本和默认的东西,所以我最终添加所有这些代码:
virtual ~SomeClass(){} // you are the guilty!
//virtual ~SomeClass() = default // would be the same
SomeClass(SomeClass&&) = default; // no more auto-added
SomeClass& operator=(SomeClass&&) = default; // no more auto-added
SomeClass(const SomeClass&) = default; // but with the moves defined,
SomeClass& operator=(const SomeClass&) = default; // I'm now missing the copy
SomeClass(){} // and the default as well
我确信有理由让我的课程变得丑陋,让我想要一个邪恶的宏观,我只是想让它感觉更舒服。
答案 0 :(得分:1)
看看this。它解释了一个称为五的规则,这基本上是标准要求的。
通常,对于大多数情况,编译器会为复制构造函数,复制赋值,移动赋值和析构函数创建默认值。但是,如果程序员定义了这些中的任何一个,那么编译器假定用户已经在这个类中封装了需要他/她特殊的东西,让我们说。析构函数。既然程序员知道他/她将需要一个析构函数,编译器就会知道程序员知道发生了什么,而不是为其余的创建默认值(因为,基于编译器的假设) make,默认值会出错,甚至可能导致不良行为。)
答案 1 :(得分:0)
问题是你的类正在尝试做两件事:提供多态接口(因此需要虚拟析构函数)和管理具体数据成员(因此需要复制/移动操作)。为每个班级承担一项责任通常是一个好主意。
我将虚拟析构函数和任何虚函数声明移动到一个空的抽象基类。那么任何具体的类都可以自由地生成所有需要的东西。
示例:
#include <iostream>
struct Movable {
Movable() {}
Movable(Movable&&m) {std::cout << "Moving\n";}
};
struct SomeInterface {
virtual ~SomeInterface() {}
// no data members, so no need for any other special member functions
};
struct SomeClass : SomeInterface {
Movable stuff;
// no user-declared special functions, so all are auto-generated
};
int main() {
SomeClass c;
SomeClass c2(std::move(c)); // uses the auto-generated move constructor
}