C++ 通过移动派生类构造基类

C++ 通过移动派生类构造基类,c++,move,C++,Move,我有一个简化的代码示例: class Base { Base() = default; Base(const Base& src) { // construct by copying src etc. - ok, legal even if src points to Derived object } Base(Base&& src) { // construct by moving src - steal

我有一个简化的代码示例:

class Base {
    Base() = default;
    Base(const Base& src) {
        // construct by copying src etc. - ok, legal even if src points to Derived object
    }

    Base(Base&& src) {
        // construct by moving src - stealing its resources, ok, it was invented for this, 
        // but.. what if src points to Derived object?
    }
};

class Derived : public Base {

};

void foo() {
    Derived derived;
    Base base_by_copy_constructor(derived); // legal, derived cannot be touched so nothing will be wrong
    Base base_by_move(std::move(derived)); // uu? what's gonna happen, part of derived object (Base class) was moved..
}
这种行为恰当吗?这可能会导致奇怪的问题,因为派生对象的基本部分实际上是“去初始化的”。 所以我们应该避免从具有move操作符的类派生,还是让我们的派生类抵制“移动”它的基部分


(当然,这只是一个例子,类没有数据,move操作符什么都不做,所以这里不会出错。我问的是一个真实世界的例子,这种情况:)

他们的切片没有问题,这可以明确而深入地完成

尽管如此,在进行面向对象编程时,通常只有一条规则:不要让对象(或组件)外部的任何实体有机会破坏不变量


因此,如果调用基类的成员或构造函数可能会破坏派生类在其与基类之间建立的不变量,那么基类必须是私有的。(您仍然可以使用base::member)将不会破坏不变量的基成员公开)

这将导致对象切片。我猜这是“不要切片对象,否则”列表中不断增加的一个新项目。移动的对象应在之后处于有效状态,因此没有真正的问题。正确编写的move构造函数会将
Base
设置为类似于
Base()=default的状态,它派生的
可能无法处理,也可能无法处理。所以“这要看情况而定”。当你有一个类的多态树时,你就必须管理和传递结果对象(可能是智能的)指向这些对象的指针。So=删除或保护复制和移动,如果需要复制,则制作返回指针的虚拟函数克隆。其余的复制/移动必须由这些指针而不是对象负责。