C++ 多态类中没有隐式复制构造函数?
在C++11中,多态类(具有C++ 多态类中没有隐式复制构造函数?,c++,c++11,constructor,destructor,C++,C++11,Constructor,Destructor,在C++11中,多态类(具有virtual成员方法的类)应该/必须具有virtual析构函数(以便基类指针上的delete执行预期的操作)。但是,声明析构函数会显式地反对隐式生成复制构造函数(尽管编译器可能不会广泛地实现这一点),因此也不会隐式生成默认构造函数。因此,要使任何多态类不被弃用,它必须具有以下成员 virtual ~polymorphic_class() = default; polymorphic_class() = default; polymorphic_class(polym
virtual
成员方法的类)应该/必须具有virtual
析构函数(以便基类指针上的delete
执行预期的操作)。但是,声明析构函数会显式地反对隐式生成复制构造函数(尽管编译器可能不会广泛地实现这一点),因此也不会隐式生成默认构造函数。因此,要使任何多态类不被弃用,它必须具有以下成员
virtual ~polymorphic_class() = default;
polymorphic_class() = default;
polymorphic_class(polymorphic_class const&) = default;
显式定义,即使它们很琐碎。我说得对吗?(这不是很烦人吗?)这背后的逻辑是什么?有什么方法可以避免这种情况吗?您是对的,将来的标准应该是这样,但现在它只是不推荐使用,所以当析构函数现在是虚拟的时,每个编译器都应该支持隐式声明的复制构造函数 n3376 12.8/7
如果类定义没有显式声明副本构造函数,则隐式声明副本构造函数。如果班级 定义声明一个移动构造函数或移动赋值运算符,即隐式声明的复制构造函数 定义为删除否则,它被定义为默认值(8.4)。如果类具有 用户声明的复制赋值运算符或用户声明的析构函数。
在我看来,你不能对此采取任何变通办法 我说得对吗 是的,按照的 有什么办法可以避免吗 对。通过为所有多态类(类似于Java和D中的classObject
,它是所有类层次结构的根)实现一个基,只需执行一次即可:
然后,从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, "");
class my\u多态性\u类:公共多态性{
};
静态断言(std::is_default_constructible::value,“”);
静态断言(std::is\u copy\u constructible::value,“”);
静态断言(std::is_copy_assignable::value,“”);
静态断言(std::is\u move\u constructible::value,“”);
静态断言(std::is\u move\u assignable::value,“”);
这背后的逻辑是什么
我不能肯定。以下只是猜测
在C++98/03中,表示如果一个类需要用户定义复制构造函数、复制赋值运算符或析构函数,那么它可能需要用户定义这三个
遵守“三个法则”是一个很好的做法,但这只不过是一个准则。标准没有强制它。为什么不呢?我的猜测是,人们只有在标准发布后才意识到这一规则
C++11引入了move构造函数和move赋值运算符,将三的规则变成了五的规则。事后诸葛亮,委员会希望执行五人规则。其思想是:如果五个特殊函数中的任何一个是用户声明的,那么除了析构函数之外的其他函数都不会隐式默认
然而,委员会不想通过强制执行此规则来破坏几乎所有C++98/03代码,然后决定只部分执行此规则:
OP中提到的和s中引用的反对意见表明,未来的标准可能会强制执行“五原则”。准备好 那么
virtual~my_class()=default代码>?多态的公共基应该是抽象的,因此无论如何都需要显式声明构造函数,以使其受保护。您仍然可以使用=default
默认构造函数,您只需要明确地提到它。@Walter:因为@KerrekSB:如果类是抽象的,为什么需要使构造函数受保护?它无论如何都不能被实例化,除非作为基类子对象,那么公共构造函数会导致什么问题呢?或者你的意思是,如果它碰巧不是一个抽象类,那么让所有构造函数受到保护就是让它“抽象”的方法,因为出于某种原因,它没有纯虚拟函数?因为如果有一件事比记录意图更好,那就是两次记录意图-p不管怎样,如果这纯粹是一个风格的东西,那么我不需要理解它,除非或者直到我在一个风格指南下工作,它规定了它。啊,可怕的“用户声明”。可惜他们没有让它成为“用户定义的”。真的。+1关于多态性基类的有趣想法。然而,你不能从它派生出一个带有noexcept
析构函数的多态类(我认为至少ICPC14.0.1会报告一个错误)。@Cassineri污损的移动语义应该标记为noexcept
@Moia这里没有必要。实际上,static\u assert(std::is\u nothrow\u move\u constructible::value,”代码>不会触发(请参阅)。另请参见中的结构B及其注释。示例前面的文本说明了=default
表示noexcept
的条件。话虽如此,它还是有用的
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, "");