Вызов переопределенной функции из переопределяющей функции - PullRequest
21 голосов
/ 13 мая 2009

Предположим, у меня есть виртуальная функция foo () в классе B, и мне нужно немного другое поведение в одном из производных классов B, классе D. Можно ли создать переопределяющую функцию D :: foo () и вызвать B: : foo () оттуда, после особого случая лечения? Как это:

void D::foo()
{
  if (/*something*/)
     // do something
  else
     B::foo();
}

Я не спрашиваю, сработает ли это, я знаю, что это сработает. Я хочу знать, правильно ли это с точки зрения хорошего OOD.

Ответы [ 7 ]

19 голосов
/ 13 мая 2009

Это прекрасно. Фактически, канонический способ выполнения некоторых операций - это вызов метода базового класса, а затем выполнение чего угодно (или наоборот). Я думаю о operator= здесь. Конструкторы обычно тоже так работают, даже если это немного замаскировано в списке инициализации.

6 голосов
/ 13 мая 2009

Да, это совершенно нормально, если вы не нарушаете принцип подстановки Лискова.

4 голосов
/ 13 мая 2009

Да, это так.

1 голос
/ 13 мая 2009

Все в порядке. Синтаксис, который вы дали, может также использоваться для временного отключения полиморфизма, т.е. когда вы вызываете obj-> B :: foo (), метод будет выбран из класса B независимо от того, является ли функция foo () виртуальной или нет, и если obj является экземпляром B или нет (хотя это должен быть экземпляр класса, расширяющего B).

1 голос
/ 13 мая 2009

Я видел, как GUI-структуры используют это, чтобы использовать стандартную реализацию базового класса, которая содержала код для оповещения об ошибках / создания исключения / возврата универсального значения.

0 голосов
/ 17 декабря 2013

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

Вы можете столкнуться с проблемой хрупкого базового класса двумя способами:

  • Предполагая, что B::foo() обеспечивает общее поведение для всей иерархии (т. Е. Забывание метода не всегда вызывается)
  • Противные проблемы в зависимости от того, что на самом деле делает // do something 1014 *

Для полноты давайте упомянем симметричный подход к проектированию: Шаблон шаблона (базовая реализация, вызывающая конкретную часть)

0 голосов
/ 13 мая 2009

Да, это именно то, что ваш компилятор делает для вас каждый раз, когда генерирует конструктор и деструктор: например, вызывает его у матери. Я часто полагаюсь на этот «трюк» в своем собственном коде.

...