此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
如何通过设置例如少于4个柱面的Engine
来使用私有继承并且在基类中没有受保护的成员来破坏此代码?
答案 0 :(得分:2)
继承引入比成员资格更紧密耦合的一种方式是派生类和基类的名称空间是混合的。因此,派生类的上下文中名称的含义取决于基类引入的名称,并且存在通常的重写/隐藏效果。基类的更改可能会对派生类中的代码产生影响,这些代码不一定明确可定位,或者会立即产生有用的诊断。相反,如果成员对象的接口发生变化,那么最多可以破解的是实际提到成员对象的代码。
答案 1 :(得分:2)
我认为问题不在于汽车可以破坏您的引擎代码,而是通过更改引擎,有人可以破坏您的汽车代码。继承表示比组合更紧密的耦合,因此Engine中的更改更可能破坏从其继承而不是包含它的类。在C ++的情况下,通过让Car包含引擎指针或智能指针来实现更松散的耦合。
答案 2 :(得分:1)
我没有看到Car可以设置Engine :: numCylinders(至少不会没有像访问原始内存那样的脏技巧)。本文中的示例使用受保护的方法,您使用私有成员。
BTW:文章以“尽可能使用合成”开头 - 而Car 有引擎,但它不是引擎。当 A 派生自 B 时,通常表示 A 是 B 。
答案 3 :(得分:0)
该文章的作者在前一点中提到了使用私有继承的一些“缺点”,here:
- 如果您想要包含多个每辆车的引擎
,则需要简单组合变体- 私有继承变体可以引入不必要的多重继承
- 私有继承变体允许Car的成员将Car *转换为Engine *
- 私有继承变体允许访问基类的受保护成员
- 私有继承变体允许Car覆盖Engine的虚函数
- 私有继承变体使得它稍微简单(20个字符与28个字符相比),为Car提供一个start()方法,只需调用Engine的start()方法