【问题标题】:How can I create derived class object from an existing base class object?如何从现有的基类对象创建派生类对象?
【发布时间】:2019-04-12 00:42:51
【问题描述】:

我正在尝试创建一个派生类对象并使用现有的基类对象填充数据成员(来自基类)。

在我的流程生命周期中,我已经有了一个基类对象。对于某些决定,我必须创建一个新对象(从基类派生)。一种方法是公开评估员并复制数据。有没有我可以使用的解决方案,如聚合初始化或 dynamic_cast?

#include <iostream>
#include <string>

using namespace std;

class Base {
    protected: 
        string name_;

    public:
        Base() : name_ ("foo")
        {
        }
        void ChangeName()
        {
            name_ = std::string {"bar"};
        }
};

class Child final : Base {
    public:
    string GetName()
    {
        return name_;
    }
};

int main()
{
    Base b;
    b.ChangeName();

    Child c = {b};
    cout<<"Hello World. Here is my name: " << c.GetName() << endl;

    return 0;
}

预期输出: 你好世界。这是我的名字:酒吧

编译错误

try.cpp:33:17: error: could not convert ‘{b}’ from ‘<brace-enclosed initializer list>’ to ‘Child’
     Child c = {b};

【问题讨论】:

  • 你有什么问题?编译错误?输出不正确? Edit您的问题以添加详细信息。
  • @1201ProgramAlarm 添加编译错误

标签: c++ c++11


【解决方案1】:

如果你想从Base 构造一个Child,你需要向Child 添加一个构造函数来实现:

Child(const Base &b): Base(b) { }

您需要谨慎使用它,因为它允许从另一个派生自Base 的类构造Child。如果Child 有任何其他数据成员,您需要确保为它们添加适当的初始化或默认值。

【讨论】:

  • 这是一个更好的解决方案,谢谢!快速提问:当我尝试 Base 的不同衍生物时,我收到以下错误:错误:'Base' is an inaccessible base of 'Child2'
  • @VarunPandey 那是因为BaseChild1 的私有基础(我也假设Child2。这将避免我提到的问题,但如果你有一个公共基类(`class Child3: public Base')构造会发生。
【解决方案2】:

使用 C 风格的强制转换可以实现这样的事情:

Child c(*(Child*)&b);

但我不建议您使用它。如果类的内存布局不相似,它可能会失败。这种情况的等效 C++ 转换如下:

Child c(*reinterpret_cast<Child*>(&b));

编辑:原来这是未定义的行为。不要尝试这个:)

【讨论】:

  • 这就是UB,简单明了。即使您认为布局匹配,将您的程序描述编译成计算机可以理解的东西的复杂性也会使这种方法完全不可靠。 避免 UB。 这一点我怎么强调都不为过。
  • 转化是UB还是会员访问?
  • 全部!您是在告诉计算机 A 是 B,而实际上不是。
  • 我明白了,谢谢你的解释。我已经更新了我的答案。
猜你喜欢
  • 2011-07-20
  • 2015-08-10
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多