Виртуальность позволяет осуществлять полиморфизм — важную концепцию объектно-ориентированного программирования, которая позволяет объектам производных классов быть обработанными через указатели или ссылки на базовый класс. Это достигается с помощью виртуальных функций, которые определяются в базовом классе и могут быть переопределены в производных классах.
🚩Виртуальные функции
Виртуальная функция определяется в базовом классе с ключевым словом
virtual. Производный класс может переопределить эту функцию. class Base {
public:
virtual void display() const {
std::cout << "Display from Base" << std::endl;
}
};
class Derived : public Base {
public:
void display() const override {
std::cout << "Display from Derived" << std::endl;
}
};🚩Как работает vtable и vptr
🟠vtable (виртуальная таблица)
Это таблица указателей на виртуальные функции класса. Каждый класс, содержащий виртуальные функции, имеет свою собственную vtable. В vtable хранятся адреса функций, которые должны быть вызваны для объектов данного класса.
🟠vptr (указатель на vtable)
Это скрытый указатель в каждом объекте класса, содержащего виртуальные функции. Он указывает на vtable соответствующего класса. Когда объект создается, vptr инициализируется, указывая на vtable его класса.
#include <iostream>
class Base {
public:
virtual void display() const {
std::cout << "Display from Base" << std::endl;
}
virtual void show() const {
std::cout << "Show from Base" << std::endl;
}
};
class Derived : public Base {
public:
void display() const override {
std::cout << "Display from Derived" << std::endl;
}
};
int main() {
Base* b = new Derived();
b->display(); // Вызовет Derived::display() благодаря vtable
b->show(); // Вызовет Base::show() поскольку она не переопределена
delete b;
return 0;
}
🚩Процесс вызова виртуальных функций
🟠При компиляции
Компилятор создает vtable для каждого класса, содержащего виртуальные функции. Компилятор также добавляет скрытый vptr в каждый объект класса, который инициализируется для указания на соответствующую vtable.
🟠При выполнении
Когда вызывается виртуальная функция через указатель или ссылку на базовый класс, программа использует vptr для доступа к vtable и вызова правильной версии функции. Это обеспечивает динамическое разрешение вызова функции (runtime polymorphism).
🚩Полиморфизм и наследование
Полиморфизм позволяет использовать базовые указатели или ссылки для работы с производными объектами, что делает код более гибким и расширяемым.
void callDisplay(const Base& obj) {
obj.display();
}
int main() {
Base b;
Derived d;
callDisplay(b); // Вызовет Base::display()
callDisplay(d); // Вызовет Derived::display()
return 0;
}Ставь 👍 и забирай 📚 Базу знаний