Ну, я проверил это для себя, потому что есть много вещей, о которых мы можем думать:
#include <iostream>
using namespace std;
class A
{
public:
virtual void v() { cout << "A virtual" << endl; }
void f() { cout << "A plain" << endl; }
};
class B : public A
{
public:
virtual void v() { cout << "B virtual" << endl; }
void f() { cout << "B plain" << endl; }
};
class C : public B
{
public:
virtual void v() { cout << "C virtual" << endl; }
void f() { cout << "C plain" << endl; }
};
int main()
{
A * a = new C;
a->f();
a->v();
((B*)a)->f();
((B*)a)->v();
}
выход:
A plain
C virtual
B plain
C virtual
Я думаю, что хороший, простой и короткий ответ может выглядеть следующим образом (потому что я думаю, что люди, которые могут понять больше, могут запомнить меньше, поэтому нуждаются в коротком и простом объяснении):
Виртуальные методы проверяют DATA экземпляра, на который указывает указатель, в то время как классические методы, таким образом, не вызывают метод, соответствующий указанному типу.
Смысл этой функции заключается в следующем: предположим, у вас есть массив А. Массив может содержать B, C (или даже производные типы). если вы хотите последовательно вызывать один и тот же метод для всех этих экземпляров, вы должны вызывать каждый из них, который вы перегружены.
Я нахожу это довольно сложным для понимания, и, очевидно, любой курс C ++ должен объяснять, как это достигается, потому что большую часть времени вас просто учат виртуальным функциям, вы их используете, но пока не поймете, как компилятор понимает их и как исполняемый файл будет обрабатывать вызовы, вы находитесь в неведении.
Особенность VFtables в том, что мне никогда не объясняли, какой код он добавляет, и именно здесь C ++ требует гораздо большего опыта, чем C, и это может быть основной причиной того, что C ++ был помечен как «медленный» в своем коде. Первые дни: на самом деле, это мощно, но, как и все, оно мощно, если вы знаете, как его использовать, или вы просто «отрываете себе ногу».