Joh*_*ohn 5 c++ constructor copy-constructor move-constructor c++11
将派生类标记为可移动而基类不可移动是否有意义\适合吗?
我知道这种不一致在 C++ 中是合法的,但它在实践中有意义\适合吗?
一般来说,我应该刻意保持这种一致性吗?
这种情况怎么样:当我打算将派生类标记为不可移动和不可复制时,我是否也应该将基类标记为不可移动和不可复制?
我做了几次测试才清楚。
这是第一个例子。由于基类是不可复制和不可移动的,因此派生类实际上是不可移动的,因为它有一个移动构造函数,这在我的期望中。提示:下面的代码片段无法编译。
#include <memory>
#include <string>
#include <iostream>
class Base {
public:
Base(){}
Base(const Base&) = delete;
Base(Base&&) = delete;
Base& operator=(const Base&) = delete;
Base& operator=(Base&&) = delete;
};
class Derived:public Base
{
public:
Derived(){}
Derived(const Derived&) = default;
Derived(Derived&&) = default;
Derived& operator=(const Derived&) = default;
Derived& operator=(Derived&&) = default;
};
int main()
{
Derived derived;
Derived derived1{std::move(derived)};
}
Run Code Online (Sandbox Code Playgroud)
这是第二个例子。基类是可复制且不可移动的,但派生类实际上是可移动的,因为在调用派生类的移动构造函数时,它会调用基类的复制构造函数,而不是基类的移动构造函数,即也在我的预料之中。提示:下面的代码片段效果很好。
#include <memory>
#include <string>
#include <iostream>
class Base {
public:
Base(){}
Base(const Base&) = default;
Base(Base&&) = delete;
Base& operator=(const Base&) = default;
Base& operator=(Base&&) = delete;
};
class Derived:public Base
{
public:
Derived(){}
Derived(const Derived&) = default;
Derived(Derived&&) = default;
Derived& operator=(const Derived&) = default;
Derived& operator=(Derived&&) = default;
};
int main()
{
Derived derived;
Derived derived1{std::move(derived)};
}
Run Code Online (Sandbox Code Playgroud)
更新:
感谢@Nightlord,他发现上面的代码片段不能用 编译Clang,这确实出乎我的意料。
小智 1
我知道这种不一致在 C++ 中是合法的,但是在实践中有意义吗?
一般来说,我应该刻意保持这种一致性吗?
是的,我认为你应该保持一致性。要使派生类可移动而基类不可移动,基类不能持有任何数据成员,否则移动未完成。
如果您的类不包含任何数据成员,您可能会将其用作接口。移动构造函数不适用于这种情况,因为客户端仅识别接口(基类)而不是具体类(派生类)。