Having a single collection containing elements with different interfaces always results in some kind of differentiation at runtime, be it dynamic_cast, QMetaType::type() or a vtable look-up as in the visitor pattern. If you don't want the differentiation at runtime you either have to
have all the elements in the collection sharing the same interface or
have a separate collection for each interface.
There is no way around that.
Even when using the visitor pattern your elements have to share the same interface (although a smaller one). I don't know how diverse your BaseKey dervived classes are, but the visitor pattern could at least prevent your base class from beeing the least common multiple of all your derived classes - at the cost of another layer of complexity.
What is your concern? Performance? Maintainability?
I possibly would use a combination if I had to eliminate the dependency of a runtime type information system and the complexity of the visitor pattern:
@
class IKey
{
public:
enum Action
{
BaseAction,
SpecialAction,
...
};
virtual void pressKey() = 0;
virtual void action(IKey::Action action) = 0;
};
class BaseKey : public IKey
{
...
void action(IKey::Action action)
{
switch(action)
{
case IKey::BaseAction:
...
break;
default:
break;
}
}
};
class SpecialKey : public BaseKey
{
...
void action(IKey::Action action)
{
switch(action)
{
case IKey::BaseAction:
BaseKey::action(IKey::BaseAction);
break;
case IKey::SpecialAction:
...
break;
default:
break;
}
}
};
class BaseClass
{
...
public:
void useKeys()
{
_useKeys(IKey::BaseAction);
}
protected:
void _useKeys(IKey::Action action)
{
IKey* key;
foreach(key, mKeys)
{
key->pressKey();
key->action(action);
}
}
};
class DerivedClass : public BaseClass
{
public:
void useKeys()
{
_useKeys(IKey::SpecialAction);
}
};
@
Brain to terminal. Not tested. Exemplary.
The switch can be replaced with a condition if every key needs to implement just one action. Won't win a design price, but I haven't seen a compromise yet that does.
[quote author="bkamps" date="1329295734"]I have also seen other 'solutions' that override the mKeys members in the derived: QVector<SpecialKey*> mKeys.[/quote]
You cannot overload or override member variables in dervied classes, you just hide them - and you end up with two seperate member variables.