#c #derived-class
Вопрос:
У меня есть следующий код:
#include<iostream>
using namespace std;
struct Base{
void f(int x){
cout<<"B";
}
};
struct Derived: public Base {
virtual void f(double x){
cout<<"D";
}
};
int main(){
Derived d;
int x = 5;
d.f(x);
Base *pb = amp;d;
pb->f(x);
}
Это выводит: DB
Даже несмотря на то, что pb хранит указатель на производный класс. Почему метод
Base
класс вызывают?
Комментарии:
1. Вы упускаете
virtual
метод базового класса. Вы не можете сделать метод виртуальным постфактум; так должно быть с самого начала.
Ответ №1:
Объявление Derived::f
виртуального не делает Base::f
виртуальным, поэтому при вызове вызывается f
указатель на Base
then Base::f
.
Вы должны объявить метод virtual
в Base
. Затем он также будет virtual
Derived
включен , вам не нужно virtual
там повторяться. В Derived
вы должны использовать override
спецификатор следующим образом:
struct Base{
virtual void f(int x){
cout<<"B";
}
};
struct Derived: public Base {
void f(double x) override {
cout<<"D";
}
};
override
Спецификатор помогает выявлять ошибки, когда метод на самом деле не override
является унаследованным методом. Например, для приведенного выше вы получите сообщение об ошибке в строке:
source>:10:10: error: 'void Derived::f(double)' marked 'override', but does not override
10 | void f(double x) override {
| ^
Типы параметров должны совпадать, когда вы хотите переопределить.
Этот код выводит ожидаемое DD
:
#include <iostream>
struct Base {
virtual void f(int x){
std::cout << "B";
}
};
struct Derived: public Base {
void f(int x) override {
std::cout << "D";
}
};
Обратите внимание, что если вы не используете override
, то такие ошибки могут остаться незамеченными. Когда классы определены следующим образом:
struct Base{
virtual void f(int x){
std::cout<<"B";
}
};
struct Derived: public Base {
void f(double x) {
std::cout<<"D";
}
};
Тогда Derived::f
не переопределяет Base::f
. Он только скрывает это, и результат все равно будет DB
.
Ответ №2:
Сначала он выводит D из-за вызова вашей функции производного класса, а затем выводит B, потому что вы просто вызываете функцию базового класса