我对么?
是的,根据ForEveR的帖子。
有没有办法避免这种情况?
是的。只需为所有多态类实现一个基(类似于Object
Java 和 D 中的类,它是所有类层次结构的根),只需执行一次:
struct polymorphic {
polymorphic() = default;
virtual ~polymorphic() = default;
polymorphic(const polymorphic&) = default;
polymorphic& operator =(const polymorphic&) = default;
// Those are not required but they don't harm and are nice for documentation
polymorphic(polymorphic&&) = default;
polymorphic& operator =(polymorphic&&) = default;
};
然后,任何公开派生的类polymorphic
都将具有隐式声明和定义(默认)的虚拟析构函数,除非您自己声明。
class my_polymorphic_class : public polymorphic {
};
static_assert(std::is_default_constructible<my_polymorphic_class>::value, "");
static_assert(std::is_copy_constructible <my_polymorphic_class>::value, "");
static_assert(std::is_copy_assignable <my_polymorphic_class>::value, "");
static_assert(std::is_move_constructible <my_polymorphic_class>::value, "");
static_assert(std::is_move_assignable <my_polymorphic_class>::value, "");
这背后的逻辑是什么?
我不能确定。以下只是猜测。
在 C++98/03 中,三法则说,如果一个类需要用户定义复制构造函数、复制赋值运算符或析构函数,那么它可能需要用户定义这三个。
遵守三法则是一个很好的做法,但这只是一个指导方针。标准并不强制它。为什么不?我的猜测是人们只有在标准发布后才意识到这个规则。
C++11 引入了移动构造函数和移动赋值运算符,将三法则变为五法则。事后看来,委员会希望执行五法则。这个想法是:如果五个特殊函数中的任何一个是用户声明的,那么其他的,但析构函数,将不会被隐式默认。
然而,委员会并不想通过强制执行此规则来破坏几乎所有 C++98/03 代码,然后决定仅部分执行:
如果移动构造函数或移动赋值运算符是用户声明的,则将删除除析构函数之外的其他特殊函数。
如果用户声明了五个特殊函数中的任何一个,则不会隐式声明移动构造函数和移动赋值运算符。
在 C++98/03 格式良好的代码的情况下,移动构造函数和移动赋值运算符都不会被用户声明,规则 1 不适用。因此,当使用符合 C++11 的编译器进行编译时,C++98/03 格式良好的代码不会因为此规则而无法编译。(如果是这样,那是出于其他一些原因。)
此外,根据规则 2,移动构造函数和移动赋值运算符没有隐式声明。这也不会破坏 C++98/03 格式良好的代码,因为他们无论如何都不会期望声明移动操作。
在 OP 中提到并在ForEveR的帖子中引用的弃用表明未来标准可能会执行五规则。做好准备!