Предварительное объявление C++ для виртуальной функции

У меня есть иерархия классов, и я пишу в ней виртуальную функцию. Скажем, есть три класса

 class A { virtual A* test(); }; ( File A.h )

 class B : public A { virtual C* test(); }; ( File B.h )

 class C : public A {}; ( File C.h )

Теперь я могу избежать включения C.h в B.h, выполнив какое-то предварительное объявление, говорящее, что C является подклассом A?

Спасибо, Гокул.


person Gokul    schedule 01.05.2010    source источник
comment
почему нужно не включать C.h в B.h? Любому клиенту B в любом случае понадобится C.h. Давайте посмотрим на вашу ситуацию шире.   -  person Ozan    schedule 01.05.2010


Ответы (3)


Вы можете сообщить компилятору только три вещи тремя разными способами о классе C:

  • Что оно существует. Вы делаете это путем прямого объявления класса.
  • Как он устроен. Вы делаете это, объявляя класс.
  • Как оно себя ведет. Вы делаете это, определяя функции-члены класса.

Если вы хотите сообщить компилятору, из чего происходит класс, вы говорите о том, как класс устроен. Затем вы должны показать компилятору объявление класса, другого пути нет.

person wilhelmtell    schedule 01.05.2010

C/C++ различают полные и неполные типы. Если вы заранее объявите class C следующим образом:

class C;

Он будет доступен как неполный тип, что означает, что вы можете объявить указатель на него. Однако вы не можете подклассифицировать его до тех пор, пока C не будет полностью объявлен, поскольку C на данный момент является неполным типом.

Вы можете использовать встроенный class C вместо C. Что вы хотите:

class B : public A { virtual class C* test(); };
person Joey Adams    schedule 01.05.2010
comment
Я думаю, вы не заметили, что виртуальная функция в классе A содержит возвращаемый тип A*. Поэтому, если я не скажу, что C является подклассом A, это не будет иметь смысла (я не хочу создавать подкласс C). Если вы чувствуете, что ответили на мой вопрос, не могли бы вы быть более ясным? - person Gokul; 01.05.2010
comment
@Gokul: я полагаю, вам нужно включить c.h. В любом случае, это выглядит как дизайнерский запах. - person UncleBens; 01.05.2010
comment
@UncleBens: я тоже думаю, что это единственный способ. Но как раз думал проверить. - person Gokul; 01.05.2010

Нет причин указывать B::test() как возвращающий C*, потому что C* всегда будет преобразовываться в A*, и любой клиент, правильно использующий интерфейс к A, будет ожидать A*. Если клиенты B ожидают только C*, они должны либо вызвать другую функцию, либо взять на себя ответственность за то, чтобы возвращенный A* восходил к C* с использованием dynamic_cast.

Также совершенно нормально объявить класс C перед классом A и заставить A::test() возвращать C* - в этом случае подклассы не имеют никакого значения при объявлении указателей на неполные типы.

person drg    schedule 01.05.2010