Указатель инкрементируется и декрементируется относительно своего базового типа. Следовательно, если указатель на базовый класс используется для доступа к объекту производного типа, инкрементирование или декрементирование не заставит его ссылаться на следующий объект производного класса. Вместо этого он будет указывать на следующий объект базового класса. Таким образом, инкрементирование или декрементирование указателя на базовый класс следует расценивать как некорректную операцию, если этот указатель используется для ссылки на объект производного класса.
Тот факт, что указатель на базовый тип можно использовать для ссылки на любой объект, выведенный из базового, чрезвычайно важен и принципиален для C++. Как будет показано ниже, эта гибкость является ключевым моментом для способа реализации динамического полиморфизма в C++.
Подобно указателям, ссылку на базовый класс также можно использовать для доступа к объекту производного типа. Эта возможность особенно часто применяется при передаче аргументов функциям. Параметр, который имеет тип ссылки на базовый класс, может принимать объекты базового класса, а также объекты любого другого типа, выведенного из него.
Динамический полиморфизм возможен благодаря сочетанию двух средств:
Функция объявляется виртуальной в базовом классе с помощью ключевого слова
Класс, который включает виртуальную функцию, называется полиморфным классом. Этот термин также применяется к классу, который наследует базовый класс, содержащий виртуальную функцию.
Рассмотрим следующую короткую программу, в которой демонстрируется использование виртуальных функций.
// Пример использования виртуальных функций.
#include
using namespace std;
class base {
public:
virtual void who() {
// объявление виртуальной функции
cout << "Базовый класс.\n";
}
};
class first_d : public base {
public:
void who() {
// Переопределение функции who() для
// класса first_d.
cout << "Первый производный класс.\n";
}
};
class second_d : public base {
public:
void who() {
// Переопределение функции who() для
// класса second_d.
cout << "Второй производный класс.\n";
}
};
int main()
{
base base_obj;
base *p;
first_d first_obj;
second_d second_obj;
p = &base_obj;
p->who(); // доступ к функции who() класса base
p = &first_obj;
p->who(); // доступ к функции who() класса first_d
p = &second_obj;