Иллюстрированный самоучитель по введению в экспертные системы

Множественное наследование в C++

При обработке этого программного кода компилятор C++ обнаружит, что вызов richard.speak)) содержит неоднозначную ссылку. Оно и понятно, поскольку нельзя однозначно заключить, скажет ли Ричард "War" (война) или "Peace" (мир).

Если мы решим, что метод speak)) класса Republican_Quaker должен "брать пример" с класса Quaker, то проблему можно решить, определив этот метод одним из двух способов:

void S::speak(){ cout << "Peace"; }

…или:

void S::speak)({Quaker::speak)); }

Первый вариант просто перегружает оба наследованных определения метода, а второй в явном виде вызывает один из них, а именно тот вариант, который реализован в классе Quaker.

Однако совершенно незначительное на первый взгляд изменение в файле определения классов может разительно изменить поведение объекта. Предположим, решено удалить объявления методов speak)) из всех классов, кроме Person, как это показано в листинге 7.3.

Листинг 7.3. Файл nixon.h. Объявление классов, версия 2.

class Person
public:
Person)) {};
virtual "Person)) {};
virtual void speak)){ cout << "Beer";}
};
class Republican: public Person
public:
Republican)) {}; virtual ~Republican)) {};
class Quaker: public Person
public:
Quaker)) {};
virtual ~Quaker)) {};
class Republican Quaker: public Republican, public Quaker
{
public:
Republican_Quaker() {};
virtual ~Republican_Quaker() {};
}

При обработке такого файла определения компилятор опять выдаст сообщение о неоднозначности ссылки на метод speak (). Это произойдет по той причине, что компилятор сформирует две копии объявления класса Person – по одной для каждого пути наследования, а это приведет к конфликту имен. Чтобы устранить эту неоднозначность, нужно объявить Person как виртуальный базовый класс и для Republican, и для Quaker. Тогда оба производных класса будут ссылаться на единственный объект суперкласса (листинг 7.4).

Листинг 7.4. Файл nixon.h. Объявление классов, версия 3.

class Person
{ public:
Per son () {};
virtual "Person)) {};
virtual void speak(){ cout << "Beer";} И
class Republican: virtual public Person
{ public:
Republican)) {};
virtual ~Republican)) {};
};
class Quaker: virtual public Person
{
public:
Quaker)) {};
virtual ~Quaker)).{};
}
class Republican_Quaker: public Republican, public Quaker
{
public:
Republican_Quaker {) { };
virtual "Republican_Quaker() {};
}
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.