从不同基类的基指针转换为基类(最好没有dynamic_cast)

时间:2012-11-26 14:12:35

标签: c++ inheritance casting multiple-inheritance

class Model {};

class AbstractModel {};
class TableModel : public AbstractModel {};

class CustomerModel : public TableModel, public Model {};
class ItemModel : public TableModel, public Model {};
...

要求是每个TableModel子类必须提供在所有子类(CustomerModel,ItemModel,...)之间共享的一组功能。由于TableModel和AbstractModel是不可变的,因此功能集在Model类中定义,并在每个子类(CustomerModel,ItemModel,...)中实现。

现在的问题是应用程序的其他部分只能访问AbstractModel指针,并且为了访问Model中定义的一组功能,这个指针必须从AbstractModel转换为Model(我们假设每个TableModel子类)也实现了Model)。

有没有可能在不使用dynamic_cast的情况下这样做? 对提供相同功能的不同设计的任何建议?

2 个答案:

答案 0 :(得分:2)

首先,如果没有dynamic_cast,这是不可能的。但是你的要求听起来有点奇怪。 “每个TableModel子类必须提供一组功能”听起来很像TableModel应该通过使用纯虚函数来定义该设置。你说TableModel是不可变的,所以我猜你从某种类型的库/框架中得到它并且正在实现你自己的一组子类,它是我们正在讨论的你的要求集。在这种情况下,我建议您派生一个TableModel的抽象类,将您的需求定义为纯虚函数,并从该抽象类派生实际实现:

//immutable/library
class AbstractModel {};
class TableModel : public AbstractModel {};

//your code:
class MyOwnTableModel : public TableModel
{
public: 
  void implementThisRequrement() = 0;
};

class CustomerModel : public MyOwnTableModel { /*...*/ };
class ItemModel : public MyOwnTableModel { /*...*/ };

之后,您需要做的只是从AbstractModel到MyOwnTableModel的简单向下转换(dynamic_cast),无需交叉投射。但是,如果你可以告诉我们更多关于你那里的设计,也许有一个更简单和更好的解决方案 - dynamic_cast几乎曾经是一些设计缺陷的证据。

答案 1 :(得分:0)

首先,为什么不使用dynamic_cast?

其次,为什么不让TableModel继承Model? (毕竟,“表模型”听起来像是“模型”的专用版本)

通过“不可变”,你的意思是在Java / .NET意义上,对象在创建后不能改变其状态吗?或者你的意思是你不能改变课程,因为他们是某些图书馆的一部分?我的第一个猜测是第一次。

如果您不想使用dynamic_cast(这是C ++的RTTI功能的一部分),您将必须实现自己的RTTI形式。例如,Microsoft的MFC通过从包含运行时类型信息的CObject超类派生所有类来实现此目的。 Microsoft COM也通过要求所有接口派生自IUnknown接口来实现这一点,IUnknown接口包含一个基本等同于dynamic_cast的QueryInterface方法。