C++中组合关系的继承

Posted

技术标签:

【中文标题】C++中组合关系的继承【英文标题】:Inheritance of composition relationship in C++ 【发布时间】:2014-12-30 16:39:03 【问题描述】:

我经常面对这个问题。假设我有这些课程:

class B

  public:
    virtual std::string className()return "B";
;

class A

  public:
    A()
    : _B(new B)
    

    virtual std::string className()return "A";

    virtual void desc()
    
      std::cout << "I am " << className() << 
        " and I own: " << _B->className() << std::endl;
    

  protected:
    B * _B;
;

然后,我想用新信息扩展AB。我确信SuperASuperB 分别与AB 具有“is-a”关系。直接的方法是尝试继承:

class SuperB: public B

  public:
    virtual std::string className()return "SuperB";


class SuperA: public A

  public:
    SuperA()
    : A()
    , _superB(new SuperB)
    

    virtual std::string className()return "SuperA";

    virtual void desc()
    
      std::cout << "I am " << className() << 
        " and I own: " << _superB->className() << std::endl;
    
  protected:
    SuperB * _superB;
;

但这显然不好,因为SuperA 实际上有两个Bs:一个来自A 类,另一个来自SuperB 类。而desc 的覆盖就没那么优雅了。

我可以看到我可以在 B* 中的 A 中设置 setter 和 getter,并在 SuperA 中覆盖它们以使用 SuperB 而不是 B,并且永远不要直接引用 B*并且总是使用 getter,但这对于 A 来说似乎有点干扰。

尝试编写,即让 SuperA 拥有一个 A* 实例看起来也不好。

如果A 拥有的不是一个B* 而是一个std::vector&lt;B*&gt;,那就更难了。

这是一个常见问题吗?有没有我看不到的优雅解决方案?

【问题讨论】:

为什么你不能在A 中有一个接受B 指针的受保护的c'tor?然后用它来构造superAA子对象superB? 您可以在SuperA 中使用_superB 的任何地方使用static_castdynamic_cast。不优雅,但可能足以满足您的目的? @StoryTeller 这是一个解决方案。不过这对 A 来说有点麻烦。 我认为解决问题的一种方法是 ASuperA 类有两个职责:它们分别将 BSuperB 适配到其他接口, 他们管理BSuperB 对象的生命周期。您可以通过仅提供转换 ctor A(B*) 等来拆分这些职责,然后提供另一种类型来管理这些对象的生命周期。 @RedWark,可能是这样,但恕我直言,这并不比从一开始就拥有一个受保护的成员更具侵入性。 【参考方案1】:

你可以让A 有一个受保护的构造函数,它接受B*

class A 
public:
    A()
    : _B(new B)
     

protected:
    A(B* b)
    : _B(b)
     
;

这样:

class SuperA : public A 
public:
    SuperA()
    : A(new SuperB)
     
;

【讨论】:

我没想到。这个解决方案实际上并不是那么具有侵入性,并且支持我在问题的后半部分中提到的向量!谢谢!

以上是关于C++中组合关系的继承的主要内容,如果未能解决你的问题,请参考以下文章

[C++]——继承赋值兼容规则与组合 (这一篇就够了!)

[C++]——继承赋值兼容规则与组合 (这一篇就够了!)

[C++]——继承赋值兼容规则与组合 (这一篇就够了!)

C++公有继承

继承的概念和意义

设计模式之美(c++)-笔记-10-组合