【问题标题】:Why does private inheritance increase the probability, as compared to composition, that someone will break my code?与组合相比,为什么私有继承会增加有人破坏我的代码的可能性?
【发布时间】:2012-02-08 18:17:21
【问题描述】:

article 的作者指出

“通常你不想访问太多其他类的内部,而私有继承给了你一些额外的权力(和责任)。但是私有继承并不邪恶;它只是更昂贵维护,因为它增加了某人更改某些内容会破坏您的代码的可能性。”

假设以下代码 Car 私下继承自 Engine :

#include <iostream>
using namespace std;

class Engine
{
    int numCylinders;
    public:
    class exception{};
    Engine(int i) { if( i < 4 ) throw exception(); numCylinders = i; }
    void start() { cout << "Engine started " << numCylinders << " cylinders" << endl; }
};

class Car : private Engine          
{    
    public:
    Car(int i) : Engine(i) {}
    using Engine::start;
};

int main()
{
    try
    {
        Car c(4);
        c.start();
    }
    catch( Engine::exception& )
    {
        cout << "A Car cannot have less than 4 cylinders" << endl;
    }
}

我的问题是:Car 如何通过设置其Engine 少于 4 个柱面、使用私有继承且在基类中没有受保护成员来破解此代码?

【问题讨论】:

  • 这是真的(根据某些真实的定义),但表达得不好。更紧密耦合的代码更难维护。

标签: c++ private-inheritance


【解决方案1】:

我认为问题不在于 Car 可以破坏您的 Engine 代码,而是通过更改 Engine,有人可以破坏您的 Car 代码。继承代表了比组合更紧密的耦合,因此引擎中的更改更有可能破坏从它继承而不是包含它的类。在 C++ 的情况下,通过让 Car 包含引擎指针或智能指针来实现更松散的耦合。

【讨论】:

    【解决方案2】:

    继承引入比成员关系更紧密耦合的一种方式是派生类和基类的名称空间混合。因此,在派生类的上下文中名称的含义取决于基类引入的名称,并且存在通常的覆盖/隐藏效果。基类中的更改可能会对派生类中的代码产生影响,这些代码不一定可以清楚地定位,或者会立即产生有用的诊断。相比之下,如果成员对象的接口发生变化,那么最能破坏的将是实际提及该成员对象的代码。

    【讨论】:

      【解决方案3】:

      我看不到 Car 可以设置 Engine::numCylinders (至少不能没有像访问原始内存这样的肮脏技巧)。文章中的示例使用受保护的方法,您使用的是私有成员。

      顺便说一句:文章以“尽可能使用组合”开头 - 汽车有一个引擎,但它不是引擎。当 A 派生自 B 时,这通常表示 A 是一个 B。

      【讨论】:

        【解决方案4】:

        文章作者,在上一点中,提到了使用私有继承的一些“弊端”,here:

        • 如果您希望每辆车包含多个引擎,则需要简单组合变体
        • 私有继承变体可能引入不必要的多重继承
        • 私有继承变体允许 Car 的成员将 Car* 转换为 Engine*
        • 私有继承变体允许访问基类的受保护成员
        • 私有继承变体允许 Car 覆盖 Engine 的虚函数
        • 私有继承变体使得为 Car 提供一个 start() 方法变得更简单(20 个字符与 28 个字符相比),该方法只需调用引擎的 start() 方法

        【讨论】:

          猜你喜欢
          • 2016-12-26
          • 1970-01-01
          • 1970-01-01
          • 2017-12-04
          • 1970-01-01
          • 2013-10-23
          • 2014-09-09
          • 2011-02-25
          • 1970-01-01
          相关资源
          最近更新 更多