【问题标题】:Constructing base class by moving derived one通过移动派生类来构造基类
【发布时间】:2018-06-28 18:26:38
【问题描述】:

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

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..
}

这样的行为合适吗?这可能会导致奇怪的问题,因为 Base part od Derived object 实际上已“取消初始化”。 所以.. 我们应该避免从具有移动运算符的类派生,还是让我们的派生类抵抗“移动”其基础部分?

(当然 - 这只是示例,类没有数据,移动运算符不做任何事情,所以这里不会出错。我问的是这种情况的真实示例:))

【问题讨论】:

  • 会导致对象切片
  • 我猜这是“不要切片你的对象,否则”这个不断增长的列表中的一个新项目。
  • 移动后的对象应该处于有效状态,所以没有真正的问题。
  • 正确编写的移动构造函数会将Base 设置为类似于Base() = default; 的状态,Derived 可能无法处理,也可能无法处理。所以“这取决于”。
  • 当你有一个多态的类树时,你必须管理并传递带有(可能是智能的)指向这些对象的指针。所以 =delete 或保护复制和移动,如果需要复制,请创建返回指针的虚拟函数克隆。其余的复制/移动必须是那些指针而不是对象的责任。

标签: c++ move


【解决方案1】:

他们对切片没有问题,这可以明确地和内在地完成。

尽管如此,一般来说,在进行 OO 编程时,只遵循一条规则:不要让对象(或组件)外部的任何实体有机会破坏不变量。

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

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2011-03-23
    • 2017-01-01
    • 2016-07-19
    • 2021-08-09
    • 2016-12-20
    相关资源
    最近更新 更多