Не зная роли различных классов, это трудно сказать, но если A
и F
интерфейсы (вероятно, случай), то дано A*
, правильный способ спросить, есть ли объект также поддерживает интерфейс F
is dynamic_cast<F*>
. Это дает указатель на интерфейс F
, если он поддерживается, и указатель на нуль в противном случае.
Кроме того, вы можете подумать, поддерживает ли интерфейс F
интерфейс A
, или полностью ли он не связан. Если это является расширением, то F
следует, вероятно, получить от A
; когда создает объект, известный для реализации расширенного интерфейса, вы назначаете его адрес F*
и избегаете всех будущих трансляций. (В общем, не назначайте на A*
, пока не достигнет точки , где некоторые из объектов указывает на хотение не реализовать F
.) Таким образом, вы в конечном итоге с чем-то вроде:
// interfaces...
class A {};
class F : public virtual A {};
// implementations of A...
class C : public virtual A {};
class B : public virtual A {};
// implementations of F (and also A, of course)
class E : public C, public virtual F {};
class D : public B, public virtual F {};
Примечание что при выходе из интерфейса обычно - хорошая идея сделать деривацию виртуальной. . (В этом случае требуется для всех дифференцированиях A
Но так же шаблон может повторяться на другом уровне, с какой-то новый класс простирающейся интерфейс F
, это вообще проще просто принять правило: вывод из интерфейс является виртуальным.)
Если F
действительно не имеет отношения к A
, тогда вы даже можете спросить, что один класс делает реализацию обоих. Или, если это имеет смысл, что некоторые (многие?) Реализации A
также реализовать F
, вы могли бы рассмотреть вопрос о предоставлении доступа к F
как часть интерфейса из A
: скажем, виртуальная функция F* A::getF() { return NULL; }
; классы, которые также реализуют F
, переопределяют эту функцию с чем-то вроде F* E::getF() { return this; }
.
Вам нужен динамический полиморфизм через виртуальные функции, а затем реализация будет выполнять всю тяжелую работу по вызову правой функции. –
Из интереса, почему вы назначили свой 'новый E()' на 'A *' в первую очередь? В ответах ниже рассматриваются несколько различных подходов. Некоторые из них меняют существующую иерархию классов, другие - нет. Может быть, ответ на этот вопрос о «A *» приводит к определенному решению. –
@SteveJessop Я должен использовать общий базовый класс, который был либо 'A', либо' F' для создания экземпляров 'E' и' D'. Ответы, предполагающие, что 'F' могут быть получены от' A' или наоборот, не соответствуют моим требованиям к дизайну, поскольку функциональность 'F' и' A' не имеет значения. 'F' не является интерфейсом, и им нужно наследовать как' E', так и 'D'.Я думаю, что я мог бы также выбрать «F» в качестве базового базового класса, но тогда мне нужно было бы использовать 'a' для' A', 'C' или' B', когда это необходимо. Пока что ваш ответ кажется лучшим решением. – Meysam