与组合相比,为什么私有继承增加了有人破坏我的代码的可能性?

发布于 2025-01-03 13:06:44 字数 1036 浏览 0 评论 0原文

这篇文章的作者指出

“通常您不想访问太多其他类的内部结构,并且私有继承为您提供了一些额外的权力(和责任),但是私有继承并不是邪恶的;它只是维护成本更高,因为它会增加。某人的概率会改变一些会破坏你的代码的东西。”

假设以下代码,其中 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤独难免 2025-01-10 13:06:44

我认为问题不在于汽车可以破坏您的引擎代码,而在于通过更改引擎,有人可以破坏您的汽车代码。继承表示比组合更紧密的耦合,因此 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.

青春有你 2025-01-10 13:06:44

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

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.

一笔一画续写前缘 2025-01-10 13:06:44

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

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

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.

羅雙樹 2025-01-10 13:06:44

文章作者在上一点中提到了使用私有继承的一些“缺点”,此处

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

The author of the article, in the previous point, refers to some of the "drawbacks" of using private inheritance, here:

  • The simple-composition variant is needed if you want to contain several Engines per Car
  • The private-inheritance variant can introduce unnecessary multiple inheritance
  • The private-inheritance variant allows members of Car to convert a Car* to an Engine*
  • The private-inheritance variant allows access to the protected members of the base class
  • The private-inheritance variant allows Car to override Engine's virtual functions
  • The private-inheritance variant makes it slightly simpler (20 characters compared to 28 characters) to give Car a start() method that simply calls through to the Engine's start() method
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文