【问题标题】:Is there a way to create an object using a pre-existing object as a sub-object of the first in C++?有没有办法使用预先存在的对象作为 C++ 中第一个对象的子对象来创建对象?
【发布时间】:2015-08-25 00:39:59
【问题描述】:

所以,假设我们有 class Parent 和继承自 class Parentclass Offspring。据我了解,当我创建一个Offspring 对象时,还会创建一个Parent 对象并与Offspring 对象相关联。问题是,如果我已经创建了一个独立的 Parent 对象,我可以将其用作 Parent 对象,该对象在创建时包含在 Offspring 对象中吗?

即是否可以不在Offspring 对象内创建新的Parent 对象,而使用原始(和独立)代替?只是将原始Parent 对象的数据复制到在Offspring 中创建的对象显然不是我想要的。

【问题讨论】:

  • 这只有在 Parent 实际上是一个接口时才有意义。然后ParentImpl 可以实现接口并拥有状态。然后Offspring 可以使用提供的ParentImpl 实现Parent 接口。
  • 您可以尝试让后代对象在其构造函数中获取对父对象的右值引用,并从该右值引用移动构造父对象。
  • 问题的存在表明您的问题是组合(特别是依赖注入)比继承更好的设计。它发生了很多......
  • 我认为从Parent派生 Offspring 完全没有意义。 Offspring 应该包含一个 指针/引用 指向一个单独的 Parent 对象。
  • @RemyLebeau:Offspring 没有理由不能同时是 Parent

标签: c++ class object inheritance nested


【解决方案1】:

这样做是有可能的。如果 Parent 有一个移动构造函数,那么你可以这样写:

class Offspring : public Parent {
  double m_x;
 public:
  Offspring(Parent && p, double x)
      : Parent(std::move(p))
      , m_x(x) 
  { }
}

我认为这是在不做危险和粗略的事情的情况下尽可能接近的。虽然这种技术可能无法避免复制 Parent 的数据,但它可以更有效。例如,如果 Parent 是 std::vector,那么上面的代码将通过从现有向量移动来初始化 Offspring 的基。这将只需要移动 24 字节的数据,而不是向量指向的所有数据。

我认为您可能想阅读以上移动语义的更多内容,看看它如何适合您的课程。

【讨论】:

  • 复制构造函数而不是移动构造函数的原理相同。
  • 这与复制数据并销毁原始数据相同。 (当然,没有其他选择)
【解决方案2】:

我相信您想要的是能够使用现有的Parent 实例和多个Offspring。我这样说是因为你似乎对复制感到担忧,而这通常不应该被关注。

您可以将Parent 定义为纯接口,并将接口本身的实现定义为表示独立的父级。

struct Parent {
    virtual ~Parent () = default;
    virtual void foo () = 0;
    //...
};

class Mother : public Parent {
public:
    void foo () { /* ... */ }
    //...
};

然后,您的Offspring 可以接受Parent 来委派实施。

class Offspring : public Parent {
    Parent &p_;
public:
    Offspring (Parent &p) : p_(p) {}
    void foo () { p_.foo(); }
    //...
};

所以现在,一个Mother 可以是多个Offspring 的父级。

Mother m;
Offspring o1(m);
Offspring o2(m);

【讨论】:

  • 在这种情况下,我根本不会从Parent派生 Offspring
  • @RemyLebeau:从功能的角度来看,我同意。但从对象关系模型来看,Offspring 没有理由不能是Parent
  • 我同意,如果 Parent 被定义为抽象接口而不是它自己的具体类,是的。
  • @RemyLebeau:我的回答文字应该已经明确了Parent应该是一个纯界面。
  • 不确定这是否是问题所要求的,但无论如何我绝不会推荐相对初学者以这种方式编码。这是一个等待发生的悬空引用,只有在特殊情况下才能证明是合理的。也许改用共享指针?
猜你喜欢
  • 2015-03-28
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 2023-01-08
  • 1970-01-01
  • 2022-11-26
  • 2019-03-02
  • 1970-01-01
相关资源
最近更新 更多