2014-01-12 62 views
0

在子类中,我需要复制基类中的字段。一个简单的例子:如果我们有一个基类Car,我想制作一辆名为DoubleCar的汽车,它代表两辆车中的一辆(有两个引擎,八个车轮等)。这个DoubleCar就像一辆汽车(我们可以启动它,加速,刹车等等),所以继承似乎很自然。我尝试做它通过以下方式如何从基类C++复制字段

class Engine{ 
    public: void Start(){} 
}; 
class Car 
{ 
    Engine* engine; 
public: 
    Car(Engine* engine){this->engine=engine;} 
    virtual void Start(){engine->Start();} 
}; 

,创造DoubleCar拥有的第一辆车从基类和secondCar为现场:

class DoubleCar : public Car 
{ 
    Car* secondCar; 
public: 
    DoubleCar(Engine* e1, Engine* e2) : Car(e1) 
    {secondCar = new Car(e2);} 
    virtual void Start(){Car::Start(); secondCar->Start();} 
}; 

该解决方案看起来丑陋,它看起来像一个汽车比另一个更重要。我也试图把两辆车都放在田里,而忽略底座成员,像这样

class DoubleCar1 : public Car 
{ 
    Car *firstCar, *secondCar; 
public: 
    DoubleCar1(Engine* e1, Engine* e2) : Car(NULL) 
    {firstCar = new Car(e1); secondCar = new Car(e2);} 
    virtual void Start(){firstCar->Start(); secondCar->Start();} 
}; 

这也不是一个好的解决方案。对于这样的问题,什么是一个好的设计?当然,在我真正的问题中,我很少有父母Car和几个孩子,所以我在一棵树的中间。

+0

'因此看起来很自然的做一个继承'看起来像你很快跳到这个结论:/特别是因为你继续使用半继承,然后假装继承! –

+0

'DoubleCar'应该和'Car'有相同的功能,这就是为什么我会得出这个结论。 – Dejan

+0

@petar为了您的代码使用['std :: shared_ptr's](http://en.cppreference.com/w/cpp/memory/shared_ptr)而不是自己处理原始指针 – Mgetz

回答

1

在我看来,一辆“双车”就像一辆卡车一样,就像“汽车”一样,而你试图强行注入继承关系的做法只是搞乱了你的概念模型。

例如,你的“双人车”不是包含两辆车。它包含的引擎数量是普通汽车的两倍,是普通汽车的两倍,但不包含两辆汽车。

我会失去对Car完全的关系,只是专注于创作这些可重用的组件类型(如Engine):

/** Has "car" in the name, but isn't a car. Cars are single-engined. */ 
class DoubleCar 
{ 
    Engine e1, e2; 

public: 
    virtual void Start() { e1.Start(); e2.Start(); } 
}; 

如果你绝望的共享接口,我会去没有比“车辆”级别更进一步,提供了一个纯粹的虚拟Start和其他任何你有。

0

一个DoubleCar应该继承汽车的公共接口数据两路车。即你需要更清晰的数据和行为分离。用Start,Stop,Accelerate, TurnLeft等方法定义汽车的抽象界面。继承您的SingleCarDoubleCar。并且用车轮,发动机等组成一个汽车组件的数据实体。在你的DoubleCar里面汇总它的两个副本。

1

通常继承模型“是一种”关系。通常这是从通用基类到更具体的派生类。例如:一辆汽车是一辆车。福特野马是一辆汽车。因此,建模您可能会得到一个基类Vehicle,然后是Car的派生类,然后是FordMustang的派生类。

现在,如果我们试图说“双车是一辆车”,那听起来有点奇怪。这不只是一辆车。这是两个。

如果我们要说“双车是由两辆车组成”,那听起来很合理。所以最终可能会有一个DoubleCar类拥有两个Car成员。这更接近你最后的想法,但不会从Car中派生出来。

在这一点上,如果我写代码,我会开始质疑我的设计。 DoubleCar是否有任何理由继承Car? “拥有相同的成员职能”还不够。你会不会需要通过一个需要汽车参考或指针的界面来提供DoubleCar?如果不是,那么也许它不应该从汽车派生出来。在这种情况下,组合构思起作用,DoubleCar本质上是一种Car容器。

但是,如果不了解更多关于实际情况的具体情况,我不确定我可以给出更好的建议。