1.5.3 Множественное наследование.

   


Назад  |  Вперёд

Если класс A является базовым классом для B, то B наследует атрибуты A. т.е. B содержит A плюс еще что-то. С учетом этого становится очевидно, что хорошо, когда класс B может наследовать из двух базовых классов A1 и A2. Это называется множественным наследованием.

Приведем некий типичный пример множественного наследования. Пусть есть два библиотечных класса displayed и task. Первый представляет задачи, информация о которых может выдаваться на экран с помощью некоторого монитора, а второй - задачи, выполняемые под управлением некоторого диспетчера. Программист может создавать собственные классы, например, такие:

           class my_displayed_task: public displayed, public task
           {
              // текст пользователя
           };

           class my_task: public task {
              // эта задача не изображается
              // на экране, т.к. не содержит класс displayed
              // текст пользователя
           };

           class my_displayed: public displayed
           {
              // а это не задача
              // т.к. не содержит класс task
              // текст пользователя
           };

Если наследоваться может только один класс, то пользователю доступны только два из трех приведенных классов. В результате либо получается дублирование частей программы, либо теряется гибкость, а, как правило, происходит и то, и другое. Приведенный пример проходит в С++ безо всяких дополнительных расходов времени и памяти по сравнению с программами, в которых наследуется не более одного класса. Статический контроль типов от этого тоже не страдает.

Все неоднозначности выявляются на стадии трансляции:

           class task
           {
           public:
             void trace ();
             // ...
           };

           class displayed 
           {
           public:
             void trace ();
             // ...
           };

           class my_displayed_task:public displayed, public task 
           {
             // в этом классе trace () не определяется
           };

           void g ( my_displayed_task * p )
           {
             p -> trace ();  // ошибка: неоднозначность
           }

В этом примере видны отличия С++ от объектно-ориентированных диалектов языка Лисп, в которых есть множественное наследование. В этих диалектах неоднозначность разрешается так: или считается существенным порядок описания, или считаются идентичными объекты с одним и тем же именем в разных базовых классах, или используются комбинированные способы, когда совпадение объектов доля базовых классов сочетается с более сложным способом для производных классов. В С++ неоднозначность, как правило, разрешается введением еще одной функции:

           class my_displayed_task:public displayed, public task 
           {
               // ...
           public:
               void trace ()
               {
                 // текст пользователя
                 displayed::trace ();  // вызов trace () из displayed
                 task::trace ();       // вызов trace () из task
               }
               // ...
           };

           void g ( my_displayed_task * p )
           {
              p -> trace ();  // теперь нормально
           }

Назад  |  Вперёд


OtDiatlovaOU
К началу книги

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.