【问题标题】:How to inherit privately from a base class' derivative, but implement public interface of the base class?如何从基类的派生中私有继承,但实现基类的公共接口?
【发布时间】:2018-05-19 02:30:28
【问题描述】:

假设库中有两个不可更改的类,AB,相关如下:

class A
{
public:
    virtual void doCustomThings() = 0;
    virtual void doOtherThings() = 0;
    void doSomething();
private:
    SomeType1 someData;
};

class B : public A
{
public:
    void doCustomThings() override;
    void doOtherThings() override;
    void someUsefulUtility();
private:
    SomeType2 otherData;
};

我正在尝试根据B 中可用的一些接口来实现A 的接口,所以我这样做了:

class C : public B
{
public:
    void doCustomThings() override; // uses B::someUsefulUtility()
    // leave B::doOtherThings() not overridden
private:
    SomeType3 myData;
};

但我不打算将C成为B,即我不希望对C 的引用可以隐式转换为B&,尽管它应该是可转换的到A&

首先想到的是使用虚拟继承,然后继承public A, private B。但是在我的例子中,AB 类是不可编辑的,为了让虚拟继承在这里工作,我需要 class B 继承为 public virtual A

另一个想法是考虑组合而不是继承。但是,如果我从A 派生并将B 作为私有成员,我将毫无用处地拥有A::someData 两次,这看起来很不雅。

考虑到上述限制,有什么好的方法可以像class C : public A, private B 这样只有一个基类A

【问题讨论】:

  • 但我不希望 C 成为 B
  • @skypjack 是的,我想让C 实现A 的虚方法。
  • 既然 B 是 A,那么 C 转换为 B 有什么关系呢?它也可以转换为 A,因为 B 是 A。
  • @ttemple 因为B 有一些我不想在C 中公开的额外功能。
  • 使 C 从 A 继承,将 B 的实现移动到单独的 h 和 cpp 中,在 B.cpp 和 C.cpp 中包含并使用此实现

标签: c++ inheritance encapsulation


【解决方案1】:

是的,使用私有继承并使用using 公开所需的成员。

class C : private B
{
public:
    using B::A;// to make it convertible to A
    using B::doOtherThings;

    void doCustomThings() override {
        std::cout<<"C::doCustomThings()\n";    
    }
private:
    char myData;
};

Working example.

【讨论】:

  • C&amp; 然后不能转换为A&amp;:例如A&amp; ac=c; 添加到您的工作示例中无法编译。
【解决方案2】:

是的,仅对A 使用继承,对B 使用组合,并委托给B 成员(不是基成员)

class C : public A
{
public:
    void doOtherThings() override { myB.doOtherThings(); }

    void doCustomThings() override {
        std::cout<<"C::doCustomThings()\n";    
    }
private:
    B myB;
    SomeType3 myData;
};

【讨论】:

  • 这如何解决重复的A::someData问题?
  • 要么你可以放心地忽略它,要么无论你选择的方案不能在所有情况下都能正常运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-10
  • 2016-10-08
  • 2017-12-29
  • 2017-04-14
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
相关资源
最近更新 更多