与组合相比,为什么私有继承增加了有人破坏我的代码的可能性?
这篇文章的作者指出
“通常您不想访问太多其他类的内部结构,并且私有继承为您提供了一些额外的权力(和责任),但是私有继承并不是邪恶的;它只是维护成本更高,因为它会增加。某人的概率会改变一些会破坏你的代码的东西。”
假设以下代码,其中 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 个,使用私有继承并且基类中没有受保护的成员?
The author of this article states that
"Normally you don't want to have access to the internals of too many other classes, and private inheritance gives you some of this extra power (and responsibility). But private inheritance isn't evil; it's just more expensive to maintain, since it increases the probability that someone will change something that will break your code."
Assume the following code where Car
inherits from Engine
privately :
#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;
}
}
My question is : how a Car
can break this code, by setting up, for example, its Engine
with less than 4 cylinders, using private inheritance and without protected members in the base class ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为问题不在于汽车可以破坏您的引擎代码,而在于通过更改引擎,有人可以破坏您的汽车代码。继承表示比组合更紧密的耦合,因此 Engine 中的更改更有可能破坏继承它的类而不是包含它的类。对于 C++,通过让 Car 包含 Engine 指针或智能指针可以实现更松散的耦合。
I think the issue isn't that Car can break your Engine code, but rather that by changing Engine, someone can break your Car code. Inheritance represents a much tighter coupling than composition, so that changes in Engine are more likely to break a class that inherits from it rather than contains it. In the case of C++, an even looser coupling is achieved by having Car contain an Engine pointer or smart pointer.
继承引入比成员资格更紧密的耦合的一种方式是派生类和基类的名称空间是混合的。因此,派生类上下文中名称的含义取决于基类引入的名称,并且存在通常的覆盖/隐藏效果。基类中的更改可能会对派生类中的代码产生影响,而派生类中的代码不一定可以清楚地定位或立即产生有用的诊断。相比之下,如果成员对象的接口发生变化,那么最可能破坏的将是实际提及成员对象的代码。
One way in which inheritance introduces a much tighter coupling than membership is that the name space of the derived and the base class is mixed. Thus the meaning of a name in the context of the derived class depends on which names the base class introduces, and there are the usual overriding/hiding effects. A change in the base class can have effects on code in the derived class that is not necessarily clearly locatable or that would immediately produce a useful diagnostic. By contrast, if the interface of a member object changes, then the most that can break will be code that actually mentions the member object.
我不认为 Car 可以设置 Engine::numCylinders (至少没有像访问原始内存这样的肮脏技巧)。文章中的示例使用受保护的方法,您使用私有成员。
顺便说一句:本文以“尽可能使用组合”开头 - 汽车有引擎,但它不是引擎。当A派生自B时,通常表示A是B。
I don't see that Car can set Engine::numCylinders (at least not without dirty tricks like accessing the raw memory). The example in the article uses a protected method, you use a private member.
BTW: The article starts with "Use composition when you can" - and a Car has an Engine, but it is not an engine. When A is derived from B then this usually expresses A is a B.
文章作者在上一点中提到了使用私有继承的一些“缺点”,此处:
The author of the article, in the previous point, refers to some of the "drawbacks" of using private inheritance, here: