#cpp #ооп
This question already has answers here: virtual и override (5 ответов) Closed 3 года назад. Многие примеры на сайтах показывают использование virtual в объявлении класса, но в дочерних нет никакого override. На msdn.microsoft.com же наоборот пихают virtual также и дочернему классу, + override. Хотелось бы узнать, вот если я вызываю из базового класса метод void Base::Method() { }, Который не переопределяется, а в этом методе используются методы, которые переопределены в дочерних классах - они будут переопределены автоматически или только в случае (Son *) (ptr)->Method2()? И как будет выглядеть ситуация в обоих случаях если virtual void Base::Method2() = 0;? Вопрос из ответа участника @ Artem.
Ответы
Ответ 1
virtual указывает, что дочерний класс может переопределить метод. Это совсем не означает, что в дочернем классе будет override. Он может быть. На msdn.microsoft.com же наоборот пихают virtual также и дочернему классу, + override. К дочернем классам добавляют virtual к методу, чтобы указать, что его потомки так же могут переопределить метод. Про вторую часть вопроса: class Base{ void Method() { bar(); } virtual void bar(); { } }; class A : public Base { virtual void bar() { } }; class B : public A { virtual void bar() { // do something } }; Сделав так: A* myObject = new B(); myObject->Method(); Вызовется метод из класса B. Собственно, возвращаясь к virtual. Я мог в классах A и B не объявлять методы как virtual, всё равно сработает метод из B. Точно так же, независимо от того, напишу я так virtual void bar() в B классе или так virtual void bar() override, тоже ничего не изменится. Что с override, что без него метод дочернего класса перекроет метод базового. Просто написав override мы явно это указываем. Очень полезно, если вы с кодом работаете не один.Ответ 2
Когда мы объявляем функцию виртуальной, используя virtual, то это равносильно тому, как если бы мы обращались к ней не напрямую, а через указатель. typedef void (*functionPointer)(ClassA*); struct ClassA { functionPointer func1; bool called; }; void callMe(ClassA* thisA) { thisA->called = true; } ClassA ca; ca.called = false; ca.func1 = callMe; ca.func1(&ca); // Будет вызвана функция callMe(). Поэтому при обращении к перекрытому методу всегда будет вызвана именно "последняя" версия функции. Даже если обращаться к ней, указывая класс-предок. C помощью override можно избежать случайного поведения наследования в коде.В следующем примере показано, в какой ситуации без использования override поведение функции-члена производного класса может быть случайным. Компилятор не выдает ошибки при использовании этого кода. class BaseClass { virtual void funcA(); virtual void funcB() const; virtual void funcC(int = 0); void funcD(); }; class DerivedClass: public BaseClass { virtual void funcA(); // ok, работает как подразумевается virtual void funcB(); // DerivedClass::funcB() не const, так что он не перекрывает // BaseClass::funcB() const и является новым методом virtual void funcC(double = 0.0); // DerivedClass::funcC(double) имеет другой // тип параметра, чем BaseClass::funcC(int), так что // DerivedClass::funcC(double) тоже новый метод }; Подробнее можно прочитать здесь.
Комментариев нет:
Отправить комментарий