Версия переопределенного метода, который вызывается, зависит от
если вы хотите вызвать функцию «через» базовый класс или «через» производный класс. Однако я нахожу, если я вызываю не переопределенный метод, а переопределенный метод вызывает некоторую функцию, которая является переопределенный, тогда версия базового класса все еще вызывается, хотя я обращаюсь к экземпляру через указатель на производный класс. Может ли кто-нибудь объяснить, почему это происходит?
КОД:
class Base {
public:
void display() {
foo();
}
void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
while (true) {}
}
версия базового класса все еще называется, хотя я получаю доступ к
экземпляр через указатель на производный класс. Может кто-нибудь объяснить
почему это происходит?
Хотя вы вызываете метод через указатель на производный класс, ваш метод не является виртуальным, поэтому используется статическая диспетчеризация, поэтому Base::display()
звонки Base::foo()
напрямую, даже если он переопределен в подклассах. Для достижения желаемого поведения вы должны использовать динамическую диспетчеризацию, то есть пометить ваши методы как virtual
,
class Base {
public:
void display() {
foo();
bar();
}
void foo() {
cout << "Base.foo()" << endl;
}
virtual void bar() {
cout << "Base.bar()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
virtual void bar() {
cout << "Derived.bar()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
}
Выход:
Base.foo()
Derived.bar()
Дело в том, что у вас нет переопределенных функций; у тебя есть скрыл свое имя.
В C ++ только виртуальные функции (см. C ++ FAQ) может быть отменено. Делая Base :: Foo () Виртуальный дает ожидаемый результат 🙁запустить код!)
class Base {
public:
void display() {
foo();
}
virtual void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
}
virtual qualifier needs to be used for methods that need to be overridden.
ex:
class Base {
public:
void display() {
foo();
}
virtual void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
virtual void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
while (true) {}
}
Вы не используете виртуальную функцию.
Объект в иерархии классов имеет два типа: это «реальный» класс и класс, который думает компилятор в тот момент, когда он имеет.
Когда вы вызываете виртуальную функцию, компилятор всегда вызывает функцию, которая принадлежит «реальному» классу. Когда вы вызываете не виртуальную функцию, компилятор вызывает функцию, принадлежащую классу, который думает это класс объектов.
Выполняя код в подклассе, компилятор думает, что * это объект подкласса. Поэтому вызов не виртуальной функции вызовет функцию, принадлежащую этому подклассу.