【问题标题】:Using private abstract method in derived class在派生类中使用私有抽象方法
【发布时间】:2016-11-15 16:54:31
【问题描述】:

我不明白以下限制:

class Base
{    
    virtual doFoo() = 0;
};

class Derived : public Base
{
public:
    void doStuff() { doFoo(); } //compile error, doFoo is a private member of Base    
};

解决方案当然是在派生类中重新声明成员,但我觉得有点奇怪:

class Derived : public Base
{
public:
    void doStuff() { doFoo(); }

private:
    virtual doFoo() = 0;
};

为什么不重新声明就不能在派生类中使用基类的抽象虚拟私有方法?这似乎是过于严格的限制,因为如果我使用它但没有定义它,那么 Derived 仍然是抽象的,并且要实例化它,一些进一步的派生类必须提供 doFoo

直观地说,通过不定义它(或重新声明它),我暗示该方法没有被使用并且不是派生类的一部分,但这对于代码的读者来说比对编译器来说更重要。或者也许编译器也确实需要这些信息,而这才是真正的原因?

【问题讨论】:

  • 为什么不使用protected?我可能错过了一些东西
  • 这些是封装的基础。私人就是私人,就是这样。如果您作为类设计者想向子类公开某些内容,请使用 protected,如果您想向所有客户端(在本例中为子类)公开您的功能,请使用 public。
  • 恕我直言,私有虚拟方法没有多大意义。虚拟意味着可以被子类覆盖,私有意味着不能从基类访问......你的意思是受保护吗?
  • @SergeBallesta 进一步限制访问实际上很有用。如果 Derived 实现了 doFoo,那么进一步的派生类将无法调用该实现。有了protected,他们就可以调用它了。
  • 那么Derived应该被声明为class Derived : private Base {...。并且没有进一步的派生类可以访问Derived 类实现。但是在基类中将方法设为私有肯定会错过重点……嗯,这看起来确实像一个 XY 问题。请准确说明您要实现的目标

标签: c++ inheritance


【解决方案1】:

不能在派生类方法中直接调用私有基类函数。然而,派生类的这种不可访问性与虚拟调用机制没有任何关系,虚拟调用机制与派生类无关。

在某些情况下这是可取的。取自C++ FAQ

你可能会问,派生类不能调用的方法有什么用?即使派生类不能在基类中调用它,基类也可以调用它,从而有效地调用(适当的)派生类。这就是模板方法模式的全部意义所在。

想想“回到未来”。假设基类是去年编写的,而您将在今天晚些时候创建一个新的派生类。基类的方法,可能几个月前已经编译并嵌入库中,将调用私有(或受保护)虚拟,这将有效地“调用未来” - 几个月前编译的代码将调用代码这甚至还不存在 - 您将在接下来的几分钟内编写的代码。您无法访问基类的私有成员 - 您无法进入过去,但过去可以进入未来并调用您尚未编写的方法。

【讨论】:

  • 所以基本上该链接进一步向下说的是“复制代码”。我可以接受重新声明,但我真的想知道是否有一些更重要的原因这不能直接使用(例如,如果需要,编译器会自行插入纯虚拟重新声明)。
  • @ForemanBob "虽然派生类不能在基类中调用it,但是基类可以调用it 有效地调用(适当的)派生类。“ it 是什么?基类中的private\protected 抽象方法?感谢您对此事的关注。
  • @Resurrection "虽然派生类不能在基类中调用it,但是基类可以调用it 有效地调用(适当的)派生类。“ it 是什么?基类中的私有\受保护抽象方法?你怎么看?
【解决方案2】:

在派生类中声明一个新成员函数不会让您访问基类中同名的成员函数。基类中的那个仍然是私有的,你不能从基类外部访问它(没有朋友声明)。这与成员函数是纯虚函数无关;它适用于所有名称。如果您不希望它是私有的,请不要将其定义为私有。

【讨论】:

    【解决方案3】:

    如果你想从派生类访问这个方法,一个好的方法是声明它protected

    这里,即使你没有将方法声明为privateclass的默认访问权限也是private。这意味着您将此方法隐式声明为private

    (如果您一直使用struct,默认访问权限将是public。)

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 2013-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-04
      相关资源
      最近更新 更多