Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多态类中没有隐式复制构造函数?_C++_C++11_Constructor_Destructor - Fatal编程技术网

C++ 多态类中没有隐式复制构造函数?

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

在C++11中,多态类(具有
virtual
成员方法的类)应该/必须具有
virtual
析构函数(以便基类指针上的
delete
执行预期的操作)。但是,声明析构函数会显式地反对隐式生成复制构造函数(尽管编译器可能不会广泛地实现这一点),因此也不会隐式生成默认构造函数。因此,要使任何多态类不被弃用,它必须具有以下成员

virtual ~polymorphic_class() = default;
polymorphic_class() = default;
polymorphic_class(polymorphic_class const&) = default;

显式定义,即使它们很琐碎。我说得对吗?(这不是很烦人吗?)这背后的逻辑是什么?有什么方法可以避免这种情况吗?

您是对的,将来的标准应该是这样,但现在它只是不推荐使用,所以当析构函数现在是虚拟的时,每个编译器都应该支持隐式声明的复制构造函数

n3376 12.8/7

如果类定义没有显式声明副本构造函数,则隐式声明副本构造函数。如果班级 定义声明一个移动构造函数或移动赋值运算符,即隐式声明的复制构造函数 定义为删除否则,它被定义为默认值(8.4)。如果类具有 用户声明的复制赋值运算符或用户声明的析构函数。

在我看来,你不能对此采取任何变通办法

我说得对吗

是的,按照的

有什么办法可以避免吗

对。通过为所有多态类(类似于Java和D中的class
Object
,它是所有类层次结构的根)实现一个基,只需执行一次即可:

然后,从
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代码,然后决定只部分执行此规则:

  • 如果移动构造函数或移动赋值运算符是用户声明的,则除析构函数外的其他特殊函数将被删除

  • 如果五个特殊函数中的任何一个是用户声明的,则不会隐式声明移动构造函数和移动赋值运算符

  • 对于C++98/03格式良好的代码,无论是移动构造函数还是移动赋值运算符都不是用户声明的,因此规则1不适用。因此,当使用符合C++11的编译器编译时,C++98/03格式良好的代码不会因为该规则而编译失败。(如果有,那是因为其他原因。)

    此外,根据规则2,移动构造函数和移动赋值运算符不是隐式声明的。这也不会破坏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, "");