daniel_pr
@daniel_pr

Почему переопределение метода без virtual -- это не переопределение?

Вот читаю википедию, и там сказано:

Переопределение метода (англ. Method overriding) в объектно-ориентированном программировании — одна из возможностей языка программирования, позволяющая подклассу или дочернему классу обеспечивать специфическую реализацию метода, уже реализованного в одном из суперклассов или родительских классов. Реализация метода в подклассе переопределяет (заменяет) его реализацию в суперклассе, описывая метод с тем же названием, что и у метода суперкласса, а также у нового метода подкласса должны быть те же параметры или сигнатура, тип возвращаемого результата, что и у метода родительского класса

Далее такой код:

struct A {
  void fn() { std::cout << "A\n"; }
};

struct B : A {
  void fn() { std::cout << "B\n"; }
};

int main() {
  B b;
  b.fn();
}

Специалисты с++ говорят, что нельзя переопределить метод, если не пометить его как virtual в базовом классе. Я согласен, но это, ведь, работает только тогда, когда идет речь о полиморфизме.

Идет вызов b.fn() и результат - "B" в консоли. То есть в структуре B реализована собственная имплементация метода fn, подменяющая тот же самый метод в базовом классе. Все согласно определнию. Так в чем же правда?

UPD:
Хорошо. Если в официальной доке с++ где-то написано "переопределение возможно тогда и только тогда, когда есть virtual у метода базового класса", то почему именно так?
  • Вопрос задан
  • 703 просмотра
Решения вопроса 2
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Это получается не переопределение, а просто метод у другого типа с таким же названием. Изначальный метод все еще можно вызвать у объекта класса (если привести тип). Также изначальный меотд доступен внутри класса потомка.

Суть переопределения в том, что это ПЕРЕопределение. Замена одной функциональности на другую. Без virtual этого не происходит.

Можно же объявить функцию fn у двух совсем не связанных классов, вызвать ее у двух экземпляров и увидеть разный результат, правда? Но тут нет никакого переопределения. Концептуально у вас тут то же самое.
Ответ написан
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Если в официальной доке с++ где-то написано "переопределение возможно тогда и только тогда, когда есть virtual у метода базового класса"

Написано, ровно это: eelis.net/c++draft/class.virtual#2

то почему именно так?

Потому что это определение термина function override в C++. Для других вариантов взаимодействия имён функций есть другие термины.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@res2001
Developer, ex-admin
Переопределить можно в любом случае, хоть с virtual, хоть без.
Но тут важно что вам надо от переопределенного метода. Если вам нужно использовать полиморфизм, то нужно ставить virttual, если нет - то нет.

Например дополним ваш пример функцией:
void func(struct A &a)
{
  a.fn();
}

int main() {
  B b;
  b.fn();
  func(b);
}

И передадим туда ссылку на b. Будет напечатана А, т.к. методы fn не виртуальные.
Если были бы виртуальные, то напечатается B - полиморфизм в действии.
Ответ написан
Комментировать
Qubc
@Qubc
Ненавижу полисемию.
В английском есть redefinition и есть overriding.
struct Base {
    void method (void) { }
    virtual methodV (void) { }
};
struct Derived : public Base {
    void method (void) { } // redefinition
    virtual methodV (void) { } // overriding // virtual можно здесь не писать.
};
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы