【问题标题】:Should private inheritance be used when there are no virtuals?没有虚拟对象时应该使用私有继承吗?
【发布时间】:2012-07-03 07:12:44
【问题描述】:

在 C++ 中,如果我有一个类 Base,它是 Derived 的私有基类,但 Base 没有虚函数,那么用类 Encapsulate 中的封装代替继承会更干净吗?我想在这种情况下继承的唯一好处是可以直接在派生类中访问基类,而不是通过memberVariable。一种或另一种做法被认为更好,还是更多的是个人风格问题?

class Base {
  public:
    void privateWork();
    // No virtual member functions here.
};

class Derived : Base {
  public:
    void doSomething() {
      privateWork();
    }
};

class Encapsulate {
    Base memberVariable;

  public:
    void doSomething() {
      memberVariable.privateWork()
    }
};

【问题讨论】:

  • 把 GoF 设计模式扔出窗外,开始编码...... :)
  • 你不应该至少有一个虚拟析构函数吗?
  • @LuchianGrigore:如果继承是私有的,那么无论如何您都无法通过基指针销毁派生的。所以我会说不一定。

标签: c++ inheritance private encapsulation


【解决方案1】:

请记住,继承模型“Liskov 替换”:当且仅当您可以将 Foo 变量传递给每个期望 Bar 的函数时,Foo 才是 Bar。私有继承不会对此建模。它对组合进行建模(Foo 是根据 Bar 实现的)。

现在,您几乎应该始终使用第二个版本,因为它更简单并且更能表达意图:对于不了解它的人来说,它不会造成混淆。

但是,有时私有继承很方便:

class FooCollection : std::vector<Foo>
{
public:
    FooCollection(size_t n) : std::vector<Foo>(n) {};

    using std::vector<Foo>::begin;
    using std::vector<Foo>::end;
    using std::vector<Foo>::operator[];
};

这允许您重用vector 的一些功能,而无需手动转发 begin、end 和 operator[] 的 2 个版本(const + non const)。

在这种情况下,你根本没有多态性:这不是继承,这是组合是伪装;您无法使用 FooCollection 作为向量。特别是,您不需要虚拟析构函数。

【讨论】:

    【解决方案2】:

    如果没有virtual 函数,则不应在OO 中使用继承。请注意,这并不意味着不能使用它,在少数(有限的)情况下,您可能需要(ab)将继承用于 OO 以外的其他目的。

    【讨论】:

    • 我相信,对于“根据”关系实现的私有继承有时是可以的。
    • @MarkB:继承是被滥用最多的特性。作为一般经验法则,继承与代码重用有关,但与大多数人认为的方向相反:应该使用继承,以便与您的基类一起使用的代码将与您的新类型一起使用(而不是滥用继承来重用功能在你的基地)。不应派生没有虚函数的类(挥手:即假设没有静态多态性):采用 Base 对象的现有代码将无法通过采用 Derived 引用来做新的事情
    • @MarkB:考虑一个具有计时器类的框架,您可以在其上注册以获得通知。该框架需要一个特定的接口来注册到计时器中(比如Notifiable)。现在考虑您想在您的应用程序中提供一个定期计时器,其中使用的确切框架只是一个实现细节。然后,您将使用私有继承来“实现”,即:从客户端的角度来看,您的类不是Notifiable 的实例,但在内部这就是您的实现方式。
    • 私有继承不建模 is-a。私有继承只不过是一种表达组合​​的便捷方式。经验法则是“不要使用它,除非它让你编写的代码少得多”(例如,你可以充分利用 using 指令)。从std::vectorusing 私下继承类中的一些vector 成员有时很方便。
    • @AlexandreC.: 这属于 (ab)use 继承用于 OO 以外的其他目的 (即它不是一个可靠的 OO 方法,尽管它可能是有意义的,因为语言的限制——元编程技巧——或更简单的语法)
    猜你喜欢
    • 2011-01-23
    • 2014-10-12
    • 1970-01-01
    • 2010-10-13
    • 2020-10-25
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    相关资源
    最近更新 更多