如何将基类对象分配给派生类对象?

and*_*iej 4 c++ inheritance

假设我有一个基类 A 和公共派生类 B,我应该如何将 A 对象分配给 B 的 A 基类子对象?

class A {...};
class B : public A {...};
A a(..);
B b(..);
static_cast<A&>(b) = a; ???
Run Code Online (Sandbox Code Playgroud)

不为 B 编写赋值运算符是否可行?将 b 转换为 A& 是否有任何潜在问题?那个标准符合吗?

9da*_*dan 6

编写另一个答案来演示为什么以及如何将基类对象分配给派生类对象。

struct TimeMachineThing_Data {
..
..
};

class TimeMachineThing : private TimeMachineThing_Data
{
    static std::stack<TimeMachineThing_Data> m_stateHistory;

    void SaveState() {
        m_stateHistory.push_back( static_cast<TimeMachineThing_Data&>(*this) );
    }

    void RestoreState() {
        static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front();
        m_stateHistory.pop_front();
    }
};
Run Code Online (Sandbox Code Playgroud)

它非常有用且完全合法。

(这里是私有继承,所以只有内部TimeMachineThing IS-A TimeMachinetime_Data)


另一个。

struct StructWithHundresField {
  string title;
  string author;
  ...

  StructWithHundresField() {
    ...
  }
};

class EasyResetClass : public StructWithHundresField {
  int not_reset_this_attriute;
public:
  void ResetToInitialStateAtAnyTime() {
    static_cast<StructWithHundresField&>(*this) = StructWithHundresField();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 不过,这很少是有用的模式。在可能的情况下,组合应该优先于私有继承。 (2认同)

Tim*_*Tim 5

这真是个坏主意。A 是基类,B 是派生类型。通过将 B 强制转换为 A,您现在正在使用 A 的赋值运算符,它不会触及任何额外的派生数据。在该赋值结束时,b仍然被认为是类型B,即使它现在包含一个A. 这与继承的使用方式相反。

将线路更改为b = reinterpret_cast<B&>(a);会更糟。然后你会假装这a是一个B当它不是,你正在阅读无效的记忆。

如果你真的想做这种任务,你需要:

class B : public A {
    B& operator= (const A& a) { ... }
};
Run Code Online (Sandbox Code Playgroud)

然后,您可以编写一个函数来复制 中的信息A,并以某种方式处理派生类型中的额外信息B,此外,您还可以简单地编写:

b = a;
Run Code Online (Sandbox Code Playgroud)

  • 我不会将分配与分配混淆。我知道该代码有效,并且不会践踏内存。我是说这是一个不好的做法,因为它的结果可能不是你想要的。正如我上面所说,您可以进行分配,而不会更改派生成员数据……但这真的是您想要的吗?如果要将派生成员设置为默认(或内插)值,请使用上面的赋值运算符。如果您真的想保留派生成员原样,请继续——只要确保了解您在做什么,并为了维护者的利益评论它。 (2认同)
  • @9dan:`A::operator=(a);` 从派生类成员函数调用基类赋值运算符没有任何问题。 (2认同)