Я хотел бы прокомментировать определение виртуального в Википедии, как повторяют некоторые здесь. [На момент написания этого ответа] Википедия определила виртуальный метод как метод, который можно переопределить в подклассах. [К счастью, с тех пор Википедия была отредактирована, и теперь она объясняет это правильно.] Это неверно: любой метод, не только виртуальный, может быть переопределен в подклассах. Что виртуальное делает, так это дает вам полиморфизм, то есть способность выбирать во время выполнения наиболее производное переопределение метода .
Рассмотрим следующий код:
#include <iostream>
using namespace std;
class Base {
public:
void NonVirtual() {
cout << "Base NonVirtual called.\n";
}
virtual void Virtual() {
cout << "Base Virtual called.\n";
}
};
class Derived : public Base {
public:
void NonVirtual() {
cout << "Derived NonVirtual called.\n";
}
void Virtual() {
cout << "Derived Virtual called.\n";
}
};
int main() {
Base* bBase = new Base();
Base* bDerived = new Derived();
bBase->NonVirtual();
bBase->Virtual();
bDerived->NonVirtual();
bDerived->Virtual();
}
Каков вывод этой программы?
Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.
Производное переопределяет каждый метод Base: не только виртуальный, но и не виртуальный.
Мы видим, что когда у вас есть Base-pointer-to-Derived (bDerived), вызов NonVirtual вызывает реализацию базового класса. Это решается во время компиляции: компилятор видит, что bDerived - это Base *, что NonVirtual не является виртуальным, поэтому он выполняет разрешение для класса Base.
Однако вызов Virtual вызывает реализацию класса Derived. Из-за ключевого слова virtual выбор метода происходит в время выполнения , а не время компиляции. Во время компиляции происходит то, что компилятор видит, что это Base *, и что он вызывает виртуальный метод, поэтому он вставляет вызов vtable вместо класса Base. Этот vtable создается во время выполнения, следовательно, разрешение во время выполнения переопределяется по большинству производных.
Надеюсь, это не слишком запутанно. Короче говоря, любой метод может быть переопределен, но только виртуальные методы дают вам полиморфизм, то есть выбор во время выполнения наиболее производного переопределения. На практике, однако, переопределение не виртуального метода считается плохой практикой и используется редко, поэтому многие люди (включая тех, кто написал эту статью в Википедии) считают, что только виртуальные методы могут быть переопределены.