Передача указателя на «класс, который наследуется от A и B» - PullRequest
2 голосов
/ 12 января 2011

У меня есть несколько абстрактных базовых классов, которые действуют как интерфейсы, известные из Java или C #, скажем, это A, B и C.

Теперь у меня есть несколько конкретных классов, каждый из которых реализует подмножество интерфейсов.:

class Concrete1: public A, public B
class Concrete2: public A, public C
class Concrete3: public A, public C

В какой-то момент я хотел бы иметь метод, который требует своего аргумента для реализации A и C (поэтому должна быть возможность передавать Concrete2 и Concrete3).

Iмог бы сделать

class AC: public A, public C
class Concrete1: public A, public B
class Concrete2: public AC
class Concrete3: public AC

и принять указатель на AC, но мне не нравится этот подход, потому что он может закончиться чем-то вроде

class AC: public A, public C
class AB: public A, public B
class ABC: public A, public B, public C
class Concrete1: public AB
class Concrete2: public AC
class Concrete3: public AC
class Concrete4: public AC, public AB, public ABC

Есть ли хорошая альтернатива?

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 12 января 2011

Прежде всего, если это публичные абстрактные базовые классы, и вы ожидаете, что сможете использовать их как типы интерфейсов, они должны быть виртуальными - в противном случае вы получите дублированные базы и проблемы с неоднозначностью.

Тем не менее, если вам нужно принять что-то, что является и "A", и "C", тогда действительно существует абстрактный базовый класс "AC", так что вы должны просто объявить это как таковой.

1 голос
/ 12 января 2011

Думаю, хорошей альтернативы не существует. Потому что эта проблема возникла из-за ошибок при первоначальной поломке интерфейса.

Если это большая нагрузка, перепроектирование интерфейсов является действительно хорошей альтернативой.

Или вы можете преодолеть с помощью шаблона, dynamic_cast, слепого броска в стиле C. Или сделайте до двух методов для каждого интерфейса.

0 голосов
/ 12 января 2011

Если AB, AB и ABC являются просто интерфейсами и никто из них не добавляет к ним какую-либо функцию new, то почему бы не написать:

class Concrete4: public ABC

вместо

class Concrete4: public AC, public AB, public ABC

Разве они не одно и то же?

Конечно, если производные интерфейсы добавляют к нему новые функции, то они не одинаковы!


Аналогично, вы можете написать ABC в терминах AB и C вместо A, B и C:

 //class ABC: public A, public B, public C
   class ABC: public AB, public C

Примечание: I 'м при условии, что A, B, C, AB, AC и ABC являются интерфейсами.т.е. все они содержат чисто виртуальные функции без определения их.И никто из них не добавляет к себе никаких новых функций, кроме функций из базового интерфейса (ов).

...