ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 9) онлайн
Неопределенность при множественном наследовании
В определенных ситуациях могут появиться некоторые проблемы, связанные со множественным наследованием. Здесь мы рассмотрим наиболее общую. Допус- тим, что в обоих базовых классах существуют методы с одинаковыми именами, а в производном классе метода с таким именем нет. Как в этом случае объект производного класса определит, какой из методов базовых классов выбрать? Одного имени метода недостаточно, поскольку компилятор не сможет вычис- лить, какой из двух методов имеется в виду. Эту ситуацию мы разберем в примере AMBIGU:
// ambigu.cpp
// демонстрация неопределенности при множественном наследовании
#include <iostream>
using namespace std;
///////////////////////////////////////////////////////////
class A
{
public:
void show ( ) { cout << "Класс A\n"; }
};
class B
{
public:
void show ( ) { cout << "Класс B\n"; }
};
class C : public A, public B
{
};
///////////////////////////////////////////////////////////
int main ( )
{
C objC; // объект класса C
// objC.show ( ); // так делать нельзя – программа не скомпилируется
objC.A::show ( ); // так можно
objC.B::show ( ); // так можно
return 0;
}
Проблема решается путем использования оператора разрешения, определя- ющего класс, в котором находится метод. Таким образом,
ObjC.A::show ( );
направляет нас к версии метода show(), принадлежащей классу A, а objC.B::show ( );
направляет нас к методу, принадлежащему классу B, Б. Страуструп (см. прило- жение 3 «Библиография») называет это устранением неоднозначности.
Другой вид неопределенности появляется, если мы создаем производный класс от двух базовых классов, которые, в свою очередь, являются производны- ми одного класса. Это создает дерево наследования в форме ромба. В программе DIAMOND показано, как это выглядит.
//diamond.cpp
// демонстрация наследования в форме ромба #include <iostream>
using namespace std;
////////////////////////////////////////////////////////////////
class A
{
public:
virtual void func();
};
class B : public A
{ };
class C : public A
{ };
class D : public B, public C
{ };
////////////////////////////////////////////////////////////////
int main()
{
D objD;
objD.func(); //неоднозначность: программа не скомпилируется
return 0;
}
Классы В и C являются производными класса A, а класс D является произ- водным классов В и C. Трудности начинаются, когда объект класса D пытается воспользоваться методом класса A. В этом примере объект objD использует метод func(). Однако классы В и C содержат в себе копии метода func(), унасле- дованные от класса A. Компилятор не может решить, какой из методов исполь- зовать, и сообщает об ошибке.
Существует множество вариаций этой проблемы, поэтому многие эксперты советуют избегать множественного наследования. Не следует использовать его в своих важных программах, пока у вас нет достаточного опыта.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
Схожі підручники
- ВИГОТОВЛЕННЯ НЕМЕТАЛЕВИХ МІНЕРАЛЬНИХ ВИРОБІВ БУДІВЕЛЬНОГО ПРИЗНАЧЕННЯ ТА ТЕХНОЛОГІЇ БУДІВНИЦТВА
- НАВЧАЛЬНИЙ ПОСІБНИК ГРОШІ ТА КРЕДИТ теорія і практика (частина 2)
- ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 1) онлайн
- Трансформаційні процеси в господарському комплексі України та їхні регіональні особливості
- Белая книга (частина 6) (онлайн)
- РАБОТА С ВОЗРАЖЕНИЯМИ ПРАКТИЧЕСКИЕ ПРИМЕРЫ УБЕЖДЕНИЯ