У меня есть 3 класса: А, Б, С. Б наследуется от А, а С наследуется от Б (таким образом, С является внуком А).
У каждого объекта есть функция говорить(), которая отображает текст, у А и Б она виртуальная.
Пусть есть внешняя функция вызов(А &a), которая берет объект А по ссылке и вызывает функцию говорить().
Отправляя объект С в функцию, она использует говорить() из Б вместо С, даже тот, что в Бговорить() виртуальный.
Почему это так? Как заставить вызывать версию из С?
#include <iostream>
using namespace std;
class A {
public:
virtual void talk() = 0;
virtual void say() = 0;
};
class B : public A {
public:
virtual void talk() // Why C does not overrides this?
{ cout << "hello\n"; }
};
class C : public B {
public:
void talk (int a) // It should override B.talk();
{ cout << "bye\n";}
virtual void say() { cout << "my name\n"; }
};
void call(A &a) {
a.talk(); // Why does it call virtual talk() from B rather than from C?
a.say(); // This was found so it knows about object C
}
int main() {
C c;
call(c);
system("PAUSE");
return 0;
}
Я ожидаю, что вызов (А & а) берет самую дальнюю версию наследования, если каждый класс между ними имеет виртуальный разговор()
В вашем примере C.talk(int)
не переопределяет B.talk()
, потому что C.talk
принимает целое число в качестве параметра, так что это совершенно другая функция.
Вы можете добавить override
после объявления функции, чтобы заставить компилятор проверить, действительно ли он что-то переопределяет:
class C : public B {
public:
// Here, the compiler complains because there's no talk(int) method
// That it can override
void talk (int a) override;
{ cout << "bye\n";}
virtual void say() { cout << "my name\n"; }
};
OMG верно, я упал так глупо сейчас из-за отсутствия параметра :/ Спасибо.
Рад, что смог помочь! :)
Вы всегда должны добавлять переопределение, чтобы четко выразить намерение переопределить базовую виртуальную функцию. Таким образом, компилятор поймает ошибку, а не загадочные сбои во время выполнения в различных вариантах.