Я использую псевдоинтерфейсы в C++, то есть чистые абстрактные классы. Предположим, у меня есть три интерфейса: IFoo, IBar и IQuux. У меня также есть класс Фред, который реализует все три из них:Проверка реализации интерфейса времени компиляции в C++
interface IFoo
{
void foo (void);
}
interface IBar
{
void bar (void);
}
interface IQuux
{
void quux (void);
}
class Fred : implements IFoo, IBar, IQuux
{
}
Я хочу объявить метод, который принимает любой объект, который реализует IFoo и IBar - это Фред будет работать, например. Только во время компиляции, способ сделать это, я могу себе представить, чтобы определить третий интерфейс IFooAndBar, который реализует как и переобъявить Фред:
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 к способу; Однако, когда я пытаюсь вызвать Фреда :: бар() непосредственно, НКУ жалуется:
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> также р roduces ошибки (которую я не понимаю)
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 к другим (ы) для обеспечения правильного типа параметров во время выполнения, но я предпочитаю время компиляции решения.
Это небезопасно и портативно. Фактически, он не определен в C++. – 2010-01-18 17:09:46