私有地继承父级,同时在C ++中公开继承祖父母

时间:2018-06-06 19:45:33

标签: c++ inheritance

标题说明了。 Parent公开公开Grandparent,我希望在Child中公开,但我想隐藏Parent本身。我不明白为什么这不可能,但我找不到使用using指令来实现这一目标的方法。如果我可以使用using公开公开私有继承的成员变量,我希望能够为私有继承的基础做同样的事情,但我似乎无法找到它的语法。 Child中的显式转换运算符可能有效,但有更简洁的方法吗?

class Grandparent {};

class Parent: public Grandparent {};

class Child: Parent
{
  // How can I expose Grandparent here publicly?
};

void takeGrandparent( Grandparent const & );

int main()
{
  takeGrandparent( Child() ); // error: cannot cast 'Child' to its private base class 'Grandparent'
}
UPD:因为人们问我为什么需要这个,这是我的用例。 GrandparentParent实现的接口。我希望Child使用Parent来实现并提供此界面,但另外保持Parent私有。

4 个答案:

答案 0 :(得分:1)

您也可以直接继承Grandparent。这需要virtual继承,通常是多重继承的情况。

class Grandparent {};

class Parent: virtual public Grandparent {};

class Child: Parent, virtual public Grandparent
{
  // No special treatment needed, interface is inherited automatically
};

这实际上在私有继承的概念中是有意义的。您可能会将私有继承视为"我太懒了,无法将Parent成员添加到Child,因此我将使用继承来实现它"。如果你这样做"正确"使用组合,它变​​得更像是具有委托的常规代码:

class Grandparent
{
public:
    virtual int GrandparentMethod() {return 8;}
};

class Parent: public Grandparent {};

class Child: public Grandparent
{
public:
    virtual int GrandparentMethod() {return parent.GrandparentMethod();}

private:
    Parent parent;
};

答案 1 :(得分:0)

不,没有“更清洁”的方式。

公共继承表示is-a关系,而private不表示。一旦您标记了Child不是Parent,您丢失的所有声明都表示ChildGrandparent - 您打破了传递链。将Child设置为Grandparent的唯一方法是Grandparent继承它 - 但我很确定你不想走这条路。

答案 2 :(得分:0)

Child方面实施Parent存在概念性问题,但仅将其设为Grandparent

这意味着Parent的契约被打破,这意味着Child的实施与Parent的实施细节密切相关。我们使用抽象和封装将我们从这些细节中分离出来是有原因的。

否则,您只需将Child设为Parent

因此,C ++从未添加任何语法来允许此操作。

答案 3 :(得分:0)

class Grandparent {
public:
  virtual void foo() = 0;
};

class Parent: public Grandparent {
public:
  virtual void foo() final { std::cout << "Dance!\n"; }
};


template<class D>
struct proxy_Grandparent:Grandparent {
  virtual void foo() final {
    return proxy().foo();
  }
private:
  D* self() { return static_cast<D*>(this); }
  D const* self() const { return static_cast<D const*>(this); }
  decltype(auto) proxy() {
    return self()->get_proxy();
  }
};

class Child: Parent,
  public proxy_Grandparent<Child>
{
  friend class proxy_Grandparent<Child>;
private:
  Parent& get_proxy() { return *this; }
};

其中有两份Grandparent;如果Grandparent是一个界面,那么这一切都不会有问题。

实际上,您应该将Parent继承更改为完全has-a:

class Child:
  public proxy_Grandparent<Child>
{
  friend class proxy_Grandparent<Child>;
private:
  Parent parent;
  Parent& get_proxy() { return parent; }
};