在定义自定义接口时继承库类

时间:2011-09-16 01:18:04

标签: c++ oop qt

我遇到了以下设计问题:

我正在为应用程序使用Qt C ++库。在这个库中有“模型”类,它们都继承自QAbstractItemModel(如QAbstractTableModelQStandardItemModel等)。我想继承其中几个类,但是要定义我们自己必须共享的接口。

我目前正在这样做的方法是定义一个接口(纯虚拟类)并让继承类继承这个。举个例子,假设我希望一个类继承QAbstractTableModel以获得doSomething函数:

class MyInterface {
public:
    virtual void doSomething() = 0;
}
class MyModel : public QAbstractTableModel, public MyInterface {
    ...
}

但是,我只想将对象作为QAbstractItemModel传递。要使用接口类,我必须将它们转换为MyInterface个对象,然后调用这些函数,这会导致遍布整个地方。此外,如果其他任何人让他们自己的类从QAbstractItemModel进入,那么如果他们不继承该接口,那么似乎还有出错的地方。

我可以使用更好的设计来完成所有这些吗?

2 个答案:

答案 0 :(得分:0)

是。首先,根本不要使用MyInterface类。当您想要获取具有doSomething()方法的任何对象时,请使用模板。如果您“将对象作为QAbstractModel传递”,这意味着您正在编写接受QAbstractModel类型的任何对象的函数,其中一些可能不是MyModel(甚至是MyInterface)。如果你打电话给doSomething,那么你违反了该函数接受QAbstractModel类型的任何对象的合同。

答案 1 :(得分:0)

您使用的是哪种铸件?如果你使用dynamic_cast,你的代码看起来不会更好但是如果你总是检查转换的null结果,你应该至少可以使用非接口类的错误。

当有大量可能的类(如MyModel,因为你无法从QAbstractTableModel直接转换(动态或静态))到MyInterface时,这会变得更复杂 - 你需要尝试向它们全部转换才能向下转换为接口类稍后的。一种解决方案可能是使用一些模板技巧 -

class MyInterface {
public:
    virtual void doSomething() = 0;
}

template <typename T>
class MyTemplatedInterface: public T, public MyInterface {
private:
    virtual void foo(){}; // might be neceseary to be able to dynamic_cast to this type
}

class MyModel: public MyTemplatedInterface<QAbstractTableModel>{
public:
virtual void doSomething(){};
}

这样,如果你得到QAbstractTableModel指针并想知道它是否实现了MyInterface,你只需要转换为MyTemplatedInterface,无论实际的基本实现类型是什么。这个设计有几个缺点,比如无法处理多个接口或声明模板化类的构造函数 - 它们中的大多数将在c ++ 0x中删除,但此时没有编译器实现足够的代码来编写代码,具体取决于它