让我们说有以下类结构:

class Car;
class FooCar : public Car;
class BarCar : public Car;

class Engine;
class FooEngine : public Engine;
class BarEngine : public Engine;

让我们也给了 Car 一个处理它的 Engine.一个 FooCar 将创建一个 FooEngine* 和一个 BarCar 将创建一个 BarEngine*.有一种方式来安排的事情,因此一个 FooCar 对象可以调员职能的 FooEngine 没有向下转换?

这里就是为什么这类结构奠定了就是现在:

  1. 所有 Car有一个s Engine.另外, FooCar 将只使用一个 FooEngine.
  2. 有数据和共享的所有算法 Engines我不想抄和粘贴。
  3. 我可能要写一职能,需要一个 Engine 要知道关于它的 Car.

只要我输入 dynamic_cast 当编写这些代码,我知道我可能做错了什么。有没有更好的方式做到这一点?

更新:

基于给出的答案迄今为止,我倾向于两种可能性:

  1. Car 提供一个纯粹的虚拟 getEngine() 功能。这将允许 FooCarBarCar 有实现,返回正确的那种 Engine.
  2. 吸收所有的 Engine 功能进入 Car 继承树。 Engine 被打破了对于维护的原因(保留 Engine 东西在一个单独的地方)。这是一个贸易之间具有更多的小类(小行代码)对具有较少的大型类。

是否有一个强大的社区的偏好的一些解决方案?是不是有第三个选择我还没有考虑?

有帮助吗?

解决方案

我假设,汽车拥有一个引擎指针,这就是为什么你发现自己向下转换.

把指针指出的基类,取而代之的是一个纯粹的虚拟get_engine()function.然后你FooCar和BarCar可持指向正确的动机类型。

(编辑)

为什么这个工作:

由于虚拟功能 Car::get_engine() 将返回 基准或指, C++将允许派生的课程来实现这个功能 不同的回报类型, ,只要返回的类型不同于通过更多的源类型。

这就是所谓 协变回归类型, ,并将允许每 Car 类型返回正确的 Engine.

其他提示

只有一件事我想添加:该设计已经味道不好我因为什么我呼吁 平行的树木.

基本上如果你结束了平行的类层次结构(如你所有的汽车,并引擎)然后你只是自寻烦恼。

我会重新考虑如果发动机(甚至汽车)需要有亚类或那些都只是不同情况下的各自相同的基础课程。

你也可以templatize的发动机型号如下

template<class EngineType>
class Car
{
    protected:
        EngineType* getEngine() {return pEngine;}
    private:
        EngineType* pEngine;
};

class FooCar : public Car<FooEngine>

class BarCar : public Car<BarEngine>

我不明白为什么一辆车不可能由一个发动机(如果BarCar将始终包含BarEngine).发动机有一个非常强有力的关系,汽车。我宁愿:

class BarCar:public Car
{
   //.....
   private:
     BarEngine engine;
}

是否有可能为FooCar使用BarEngine?

如果不是,你可能希望使用AbstractFactory创造合适的汽车对象,有正确的动机。

你可以存储FooEngine在FooCar,BarEngine在BarCar

class Car {
public:
  ...
  virtual Engine* getEngine() = 0;
  // maybe add const-variant
};

class FooCar : public Car
{
  FooEngine* engine;
public:
  FooCar(FooEngine* e) : engine(e) {}
  FooEngine* getEngine() { return engine; }
};

// BarCar similarly

这种方法的问题是,得到一个引擎是一个虚拟的电话(如果你关心有关),一方法 设置 一个在引擎 Car 将需要向下转换.

我认为,它取决于如果 Engine 只是私下使用的 Car 及其的儿童,或者如果你还想用它在其他的对象。

如果 Engine 功能都不具体到 Cars,我会使用 virtual Engine* getEngine() 方法,而不是保持一个指在基类。

如果它的逻辑是具体到 Cars,我宁愿把共同的 Engine 数据/逻辑在一个单独的目的(不一定是多形态)以及保持 FooEngineBarEngine 执行在他们各自的 Car 孩子类。

当执行回收利用更多的必要界面的继承,目的组成往往提供更大的灵活性。

微软的COM是种笨重的,但它不会有一个新的概念-如果你有一个指向一个接口的一个目的,你可以查询其看如果它支持任何其他接口的使用 QueryInterface 功能。这个想法是要打断你的动机类成多个接口,以便每个可独立使用。

允许我没有错过的东西,这应该是相当微不足道的。

最好的方式来做到这一点是创造纯粹的虚拟的功能的引擎,然后需要在得出类别将实例化。

一个额外的信贷方案可能有一个界面称为IEngine,你而不是passs到你的车,每一个功能IEngine是纯粹的虚拟的。你可以有一个'BaseEngine',实现了一些功能你想要的(即,'共享'),然后叶的。

该接口是不错的你应该永远拥有你想要的东西'看起来像一个引擎,但可能不是(即,模拟测试的课程和诸).

有一种方式来安排的事情,这样一个FooCar对象可以调员职能的FooEngine而不向下转换?

是这样的:

class Car
{
  Engine* m_engine;
protected:
  Car(Engine* engine)
  : m_engine(engine)
  {}
};

class FooCar : public Car
{
  FooEngine* m_fooEngine;
public:
  FooCar(FooEngine* fooEngine)
  : base(fooEngine)
  , m_fooEngine(fooEngine)
  {}
};
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top