- •Полиморфизм
- •Способность объектно-ориентированных языков автоматически определять тип объекта
- •Виртуальные функции имеет смысл использовать только для классов, являющихся базовыми.
- •Правило: указатель на базовый класс может ссылаться на объект этого класса или любого
- •Пример. Использование указателей на классы.
- •int main(){
- •Пример. Использование виртуальных функций.
- •void sound(Animal& i)
- •Переопределим класс Animal:
- •Пример. Использование указателей на объекты. Приведение типов.
- •class Dog: public Animal
- •int main()
- •Механизм работы позднего связывания
- •В каждом классе также помещается указатель VFPTR на таблицу виртуальный функций.
- •При явном связывании мы получаем
- •Для указателей, имеющих тип базового класса, компилятор запрещает вызовы тех виртуальных функций, которые
- •Абстрактные базовые классы
- •Пример. Работа с абстрактным классом
- •Чистые виртуальные функции могут быть определены, но только вне объявления класса.
- •class Dog: public Animal
- •char *eat() {
- •Виртуальные деструкторы class Base1
- •class Base2
- •int main()
- •Чистые виртуальные деструкторы
- •Виртуальные функции в деструкторах
- •int main {
- •Пример. Перегруженные переопределённые функции
- •class Derived2: public Base { public:
- •int main() { char *s;
- •Множественное наследование
- •Вызов конструкторов при создании объекта класса D происходит в том порядке, в котором
- •class A { public:
- •class C: public A, public B { public:
- •Виртуальный базовый класс
- •class A:public virtual W { public:
- •int main() {
- •Виртуальные базовые классы инициализируются перед любыми невиртуальными базовыми классами в том порядке, в
- •Пример. Использование одного класса в качестве виртуального и невиртуального базового класса
int main() {
C* pc = new C; pc->f(); pc->g(); pc->h(); ((A*)pc)->f(); ((W*)pc)->f(); delete pc;
B* pb = new B; pb->f(); pb->g(); pb->h();
((W*) pb)->f(); delete pb;
A* pa = new A; pa->f(); pa->g(); pa->h();
((W*) pa)->g(); delete pa; return 0;
}
Для описания иерархий множественного наследования используется прямой ациклический граф.
Виртуальные базовые классы инициализируются перед любыми невиртуальными базовыми классами в том порядке, в котором они появляются в прямом ациклическом графе наследования при просмотре его снизу вверх и слева направо.
Для рассмотренного примера порядок вызова конструкторов следующий:
W::W();
A::A();
B::B();
C::C();
Пример. Использование одного класса в качестве виртуального и невиртуального базового класса
class A {...}; |
|
class B: public virtual A {... |
}; |
class C: public virtual A {... |
}; |
class D: public A {...}; |
|
class E: public B, public C, public D {};
|
|
|
A |
|
|
|
|
|
A |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
B |
C |
D |
E
Порядок вызова конструкторов:
A::A();
B::B();
C::C();
A::A();
D::D();
E::E();