Я использую псевдоинтерфейсы в C ++, то есть чисто абстрактные классы.Предположим, у меня есть три интерфейса: IFoo, IBar и IQuux.У меня также есть класс Fred, который реализует все три из них:
interface IFoo
{
void foo (void);
}
interface IBar
{
void bar (void);
}
interface IQuux
{
void quux (void);
}
class Fred : implements IFoo, IBar, IQuux
{
}
Я хочу объявить метод, который принимает любой объект, который реализует IFoo и IBar - например, работал бы Fred.Единственный способ сделать это во время компиляции, который я могу себе представить, это определить третий интерфейс IFooAndBar, который реализует оба, и переопределить Fred:
interface IFooAndBar : extends IFoo, IBar
{
}
class Fred : implements IFooAndBar, IQuux
{
}
Теперь я могу объявить мой метод как получающий IFooAndBar *.Пока все хорошо.
Однако что произойдет, если я также захочу другой метод, который принимает IBar и IQuux?Я попытался объявить новый интерфейс IBarAndQuux и объявить Фреда как унаследованного:
class IFooAndBar : IFoo, IBar
{
};
class IBarAndQuux : IBar, IQuux
{
};
class Fred : IFooAndBar, IBarAndQuux
{
};
Это работает, когда я передаю Фреду метод IFooAndBar методу;однако, когда я пытаюсь вызвать Fred :: bar () напрямую, gcc жалуется:
error: request for member ‘bar’ is ambiguous
error: candidates are: void IBar::bar()
error: void IBar::bar()
, что делает это решение более или менее бесполезным.
Моя следующая попытка состояла в том, чтобы объявить Фреда как наследующего от трех отдельных интерфейсов и заставить метод принять один из гибридных интерфейсов в качестве параметра:
class Fred : public IFoo, public IBar, public IBaz
{
};
void doTest (IBarAndBaz* pObj)
{
pObj->bar();
pObj->baz();
}
Когда я пытаюсь передать Фреда как параметр IBarAndBaz *, Я получаю ошибку, как и ожидалось:
error: cannot convert ‘Fred*’ to ‘IBarAndBaz*’ for argument ‘1’ to ‘void doTest(IBarAndBaz*)’
dynamic_cast <> также выдает ошибку (которую я не понимаю)
error: cannot dynamic_cast ‘pFred’ (of type ‘class Fred*’) to type ‘class IBarAndBaz*’ (source type is not polymorphic)
Принудительное приведение делает работают, однако:
doTest((IBarAndBaz*)pFred);
но мне интересно, насколько это безопасно и переносимо (я разрабатываю для Linux, Mac и Windows) и работает ли оно в реальной ситуации.
Наконец, я понимаю, что мой метод может принимать указатель на один из интерфейсов и dynamic_cast на другой (ие) для принудительного применения правильного типа параметра во время выполнения, но я предпочитаю время компиляциирешение.