Добавил:
Developer Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Магистратура Языки программирования С,C++ / Доклад на тему №8 Наследование, перегрузка, переопределение.docx
Скачиваний:
3
Добавлен:
17.03.2024
Размер:
1.31 Mб
Скачать

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().