派生自抽象基类,具有用户声明的医生和移动支持



用户声明的doctor可以防止自动生成move- action/-assign -operator。但是,自动生成是否只在定义了doctor的类中被阻止,还是在所有派生类中也被阻止?我之所以问这个问题,是因为我使用了许多纯虚拟类,它们都提供了一个用户声明的doctor。我现在是否必须升级所有这些职业才能获得移动支持,或者它仍然可以开箱即用?

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

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:Nothing to do

在基类中没有移动构造函数和在基类中删除移动构造函数是两码事。

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

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

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

Cpp参考说:

T的隐式声明或默认移动构造函数被定义为删除,如果以下任何一个为真:

T具有不能移动的直接基类或虚拟基类(具有删除的、不可访问的或模糊的move构造函数);…

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

最新更新