从具有用户声明的 dtor 和移动支持的抽象基础派生

问题描述

用户声明的 dtor 阻止自动生成 move-ctor/-assignment-operator, 但是只有在定义了 dtor 的类中才会阻止自动生成,还是在所有派生类中也会阻止自动生成?我问这个,因为我使用了许多纯虚拟类,它们都提供用户声明的 dtor。我现在必须升级所有这些类才能获得移动支持还是开箱即用?

以下是我的场景当前的示例:

struct BigData {};

struct BaseA
{
    virtual void func() = 0;
    virtual ~BaseA() = default;
};

struct A : public BaseA
{
    BigData _data;
    void func() override {}
};

现在,我必须使用以下哪些变体 可以肯定,移动将在下面使用 例子?

A a;
std::vector< A > va;
va.push_back( std::move( a ) ); //Should really use move instead of copy

变体 1:仅升级基类

struct BaseA
{
    virtual void func() = 0;
    virtual ~BaseA() = default;

    BaseA() = default;
    BaseA(BaseA&&) = default;
    BaseA& operator=(BaseA&&) = default;
    BaseA(const BaseA&) = default;
    BaseA& operator=(const BaseA&) = default;
};

struct A : public BaseA
{
    BigData _data;
    void func() override {}
};

变体 2:仅升级派生类

struct BaseA
{
    virtual void func() = 0;
    virtual ~BaseA() = default;
};

struct A : public BaseA
{
    BigData _data;
    void func() override {}
    A() = default;
    A(A&&) = default;
    A& operator=(A&&) = default;
    A(const A&) = default;
    A& operator=(const A&) = default;
};

变体 3:升级基类和派生类

struct BaseA
{
    virtual void func() = 0;
    virtual ~BaseA() = default;

    BaseA() = default;
    BaseA(BaseA&&) = default;
    BaseA& operator=(BaseA&&) = default;
    BaseA(const BaseA&) = default;
    BaseA& operator=(const BaseA&) = default;
};

struct A : public BaseA
{
    BigData _data;
    void func() override {}
    A() = default;
    A(A&&) = default;
    A& operator=(A&&) = default;
    A(const A&) = default;
    A& operator=(const A&) = default;
};

变体 4:无事可做

解决方法

在基类中没有移动构造函数与在基类中具有已删除的移动构造函数是两件不同的事情。

对于第一个,派生类仍然可以遵循零规则,并具有编译器创建的默认生成移动构造函数。

对于后者,在派生中也会删除默认的移动。

当您的类中有用户定义的析构函数(或用户定义的复制构造函数,或用户定义的复制赋值运算符)时,不会提供默认的移动操作,但不会隐式删除它们。因此,如果派生类遵循默认移动操作的规则,则它仍然有权进行默认移动操作,而无需将它们显式声明为 =default

Cpp 参考 says

如果满足以下任一条件,则类 T 的隐式声明或默认移动构造函数被定义为已删除:

... T 具有无法移动的直接或虚拟基类(已删除、不可访问或不明确的移动构造函数); ...

请注意,用户声明析构函数不会使类不可移动,它只是没有默认生成的移动。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...