Inheriting library class while defining custom interface
I'm running into the following design problem:
I'm using the Qt C++ libra开发者_开发技巧ry for an application. In this library there are the "model" classes which all inherit from QAbstractItemModel
(like QAbstractTableModel
, QStandardItemModel
, etc.). I want to inherit from several of these classes but define my own interface they must each share.
The way I'm currently doing this is by defining an interface (pure virtual class) and having the inheriting classes inherit from this as well. As an example, let's say I want a class to inherit from QAbstractTableModel
to have a doSomething
function:
class MyInterface {
public:
virtual void doSomething() = 0;
}
class MyModel : public QAbstractTableModel, public MyInterface {
...
}
However, I just want to pass objects around as a QAbstractItemModel
. To use the interface classes I have to cast them to MyInterface
objects and then call the functions, which leads to casts all over the place. Further, if anyone else makes their own class inhheriting from QAbstractItemModel
it seems like there's room for error if they do not inherit the interface as well.
Is there a better design I could be using to accomplish all this?
Which kind of casting are you using? if you use dynamic_cast, your code will not look better but if you always check for null-result of casting the you should at least be ok with possible errors with non-interfaced classes.
This gets more complicated when there is large set of possible classes like MyModel becuase you cannot directly cast (dynamic or static) from QAbstractTableModel to MyInterface - you would need to try casting to them all in order to down-cast to interface class later on. One solution might be to do it with some template trick -
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(){};
}
This way if you get QAbstractTableModel pointer and want to know if it implements MyInterface you just cast to MyTemplatedInterface, no matter what actual base implementation type is. This design has several flaws, like inability to handle more than one interface or declaring constructors of the templated class - most of them will be removed in c++0x, but at this point no compiler implements enough of it to write code depending on it.
Yes. first, don't use the MyInterface class at all. Use templates for when you want to take any object that has a doSomething() method. If you are "passing object around as QAbstractModel" that implies you are writing functions that accept any object of type QAbstractModel, some of which might not be MyModel's (or even MyInterface's). If you make a call to doSomething, then you are violating the contract that the function accept any object of type QAbstractModel.
精彩评论