
- •Содержание
- •1 Наследование
- •1.1 Типы наследования
- •1.2 Множественное наследование
- •1.3 Проблематика множественного наследования
- •1.4 Проблема ромбовидного наследования
- •1.5 Проблема ромбовидного наследования: Конструкторы и деструкторы
- •1.6 Интерфейс
- •1.7 Вывод по наследованию
- •2 Неявное приведение типов
- •4 Перегрузка
- •4.1 Правила перегрузки
- •5.1 Требования для переопределения функции
- •5.2 Привязка вызова функции к объектам класса
- •6 Виртуальные методы и таблица виртуальных методов
- •Принцип работы
- •6.1 Виртуальное наследование
- •6.2 Абстрактный класс
- •7 Виртуальные методы в конструкторе и деструкторе
- •Список использованных источников
1.2 Множественное наследование
Множественное наследование происходит, когда подкласс имеет два или более суперкласса. В этом примере, класс Laptop наследует и Monitor и Computer одновременно.
Листинг №1.2.1 – Программный код
#include <iostream>
using namespace std;
class Computer {
public:
void turn_on() {
cout << "Welcome to Windows 95" << endl;
}
};
class Monitor {
public:
void show_image() {
cout << "Imagine image here" << endl;
}
};
class Laptop : public Computer, public Monitor {};
int main() {
Laptop Laptop_instance;
Laptop_instance.turn_on();
Laptop_instance.show_image();
return 0;
}
1.3 Проблематика множественного наследования
Множественное наследование требует тщательного проектирования, так как может привести к непредвиденным последствиям. Большинство таких последствий вызваны неоднозначностью в наследовании. В данном примере Laptop наследует метод turn_on() от обоих родителей и неясно какой метод должен быть вызван.
Листинг №1.3.1 – Программный код
#include <iostream>
using namespace std;
class Computer {
private:
void turn_on() {
cout << "Computer is on." << endl;
}
};
class Monitor {
public:
void turn_on() {
cout << "Monitor is on." << endl;
}
};
class Laptop : public Computer, public Monitor {};
int main() {
Laptop Laptop_instance;
// Laptop_instance.turn_on();
// will cause compile time error
return 0;
}
Несмотря на то, что приватные данные не наследуются, разрешить неоднозначное наследование изменением уровня доступа к данным на приватный невозможно. При компиляции, сначала происходит поиск метода или переменной, а уже после — проверка уровня доступа к ним.
1.4 Проблема ромбовидного наследования
Рисунок 1.4.1 – Ромбовидное наследование
Проблема ромба (Diamond problem) - классическая проблема в языках, которые поддерживают возможность множественного наследования. Эта проблема возникает, когда классы B и C наследуют A, а класс D наследует B и C.
К примеру, классы A, B и C определяют метод print_letter(). Если print_letter() будет вызываться классом D, неясно какой метод должен быть вызван — метод класса A, B или C. Разные языки по-разному подходят к решению ромбовидной проблем. В C ++ решение проблемы оставлено на усмотрение программиста.
Ромбовидная проблема — прежде всего проблема дизайна, и она должна быть предусмотрена на этапе проектирования. На этапе разработки ее можно разрешить следующим образом:
вызвать метод конкретного суперкласса;
обратиться к объекту подкласса как к объекту определенного суперкласса;
переопределить проблематичный метод в последнем дочернем классе (в коде — turn_on() в подклассе Laptop).
Листинг №1.4.1 – Программный код
#include <iostream>
using namespace std;
class Device {
public:
void turn_on() {
cout << "Device is on." << endl;
}
};
class Computer : public Device {};
class Monitor : public Device {};
class Laptop : public Computer, public Monitor {
/*
public:
void turn_on() {
cout << "Laptop is on." << endl;
}
// uncommenting this function will resolve diamond problem
*/
};
int main() {
Laptop Laptop_instance;
// Laptop_instance.turn_on();
// will produce compile time error
// if Laptop.turn_on function is commented out
// calling method of specific superclass
Laptop_instance.Monitor::turn_on();
// treating Laptop instance as Monitor instance via static cast
static_cast<Monitor&>(Laptop_instance).turn_on();
return 0;
}
Если метод turn_on() не был переопределен в Laptop, вызов Laptop_instance.turn_on(), приведет к ошибке при компиляции. Объект Laptop может получить доступ к двум определениям метода turn_on() одновременно: Device:Computer:Laptop.turn_on() и Device:Monitor:Laptop.turn_on().