У меня есть интерфейс и класс, реализующий его:
class InterfaceA
{
public:
enum Enum { X, Y, Z };
virtual void foo(Enum &) = 0;
virtual void bar() = 0;
};
class ClassA : public InterfaceA
{
public:
virtual void foo(Enum & a) {
a = X;
}
virtual void bar();
};
Мне нужно расширить функциональность класса реализации InterfaceA в одном аспекте. В моем понимании это то, для чего нужны миксины.
Например. foo () должна изменить значение своего параметра при некоторых условиях. Вот как я это делаю:
template <typename T>
class Mixin : public T
{
public:
virtual void foo(Enum & a) {
T::foo(a);
if (a == X){
a = Y;
}
}
};
Проблема в том, что он не скомпилируется, если я не запишу префиксы области для идентификаторов, определенных в классе интерфейса, или не опишу их так:
template <typename T>
class Mixin : public T
{
public:
typedef InterfaceA::Enum Enum;
virtual void foo(Enum & a) {
T::foo(a);
if (a == InterfaceA::X){
a = InterfaceA::Y;
}
}
};
Это не имеет большого значения, если из определения интерфейса мало таких типов. Но если их много, это может стать уродливым. Я хотел бы, чтобы код отражал тот факт, что Mixin манипулирует объектом InterfaceA по своему дизайну. К сожалению, наследование Mixin от InterfaceA представляет «ужасный бриллиант», которого мне лучше избегать. Это возможно?
Enum
, X
а также Y
должно быть зависимое имя.
И вы можете использовать static_assert
заставить наследство.
template <typename T>
class Mixin : public T
{
public:
static_assert(std::is_base_of<InterfaceA, T>::value,
"T should inherit from InterfaceA");
virtual void foo(typename T::Enum & a) {
T::foo(a);
if (a == T::X){
a = T::Y;
}
}
};
Я полагаю, вы должны использовать виртуальное наследование; это должно избежать проблемы «страшного алмаза».
Что-то вроде
class InterfaceA
{
public:
enum Enum { X, Y, Z };
virtual void foo(Enum &) = 0;
virtual void bar() = 0;
};
class ClassA : public virtual InterfaceA
{
public:
virtual void foo(Enum & a) {
a = X;
}
virtual void bar() {
}
};
template <typename T>
class Mixin : public T, public virtual InterfaceA
{
public:
virtual void foo(Enum & a) {
T::foo(a);
if (a == X){
a = Y;
}
}
};int main ()
{
Mixin<ClassA> m;
return 0;
}