|
Программирование >> Структурное программирование
Si FIG9 11.CPP Драйвер примера множественного наследования tinclude <iostream.h> i tinclude basel.h tinclude base2.h tinclude derived.h main() Basel bl(lO), *baselPtr; Base2 b2(Z), *base2Ptr; Derived d(7, A, 3.5); создание объекта базового класса создание объекта другого базового класса создание объекта производного класса печать данных-элементов объектов базового класса cout Объект Ь1 содержит целое Ь1.getDataO endl Объект Ь2 содержит символ Ь2. getDataO endl Объект d содержит: endl d endl endl; печать данных-элементов объекта производного класса операция разрешения области действия устраняет неопределенность getData cout Элементы данных класса Derived могут быть << доступны индивидуально: endl Целое: d.Basel::getData() endl Символ: d.Base2::getDataО endl Действительное: d.getRealO endl endl; cout << Derived может трактоваться как объект обоих базовых классов: endl; трактовка Derived как объекта класса Basel baselPtr = &d; cout Результат baselPtr->getData() baselPtr->getDataО endl; трактовка Derived как объекта класса Base2 base2Ptr = &d; cout Результат base2Ptr->getData0 base2Ptr->getDataО endl; return 0; Рис. 9.11. Драйвер примера множественного наследования (чааь 5 из 6) [ Объект Ы содержит целое 10 Объект Ь2 содержит символ Z Объект d содержит: \ Целое: 7 fVji Символ: А Действительное: 3.5 Элементы дгшных класса Derived могут быть доступны индивидуально: * I Целое: 7 Символ: А Действительное: 3.5 Derived может трактоваться как объект обоих базовых классов: Результат baselPtr->getData() 7 НН Результат base2Ptr->getData() А Рис. 9.11. Пример множественного наследования (часть 6 из 6) Теперь давайте рассмотрим программу драйвер в main. Мы создаем объект Ы класса Basel и задаем целому начальное значение 10. Затем мы создаем объект Ь2 класса Base2 и задаем символу начальное значение Z. Наконец, мы создаем объект d класса Derived и задаем начальные значения 7 для целого, А для символа и 3.5 для действительного элементов. Содержание каждого из объектов базового класса печатается путем вызовов функции-элемента getData для каждого объекта. Несмотря на существование двух функций getData, вызовы не являются неопределенными, потому что они ссылаются непосредственно на версию функции getData объекта Ы и на версию функции getData объекта Ь2. Далее мы печатаем содержимое объекта d класса Derived с помощью статического связывания. Но здесь мы имеем проблему неопределенности, потому что один объект содержит две функции getData, одну, унаследованную от Basel, и одну, унаследованную от Base2. Эта проблема легко решается с помощью бинарной операции разрешения области действия: d.Basel::get-Data(), чтобы напечатать целое value, и d.Base2::getData(), чтобы напечатать символ letter. Значение float в real печатается без неопределенности с помощью вызова d.getReal(). Далее мы показываем, что отношения является простого наследования применимы и к множественному наследованию. Мы присваиваем адрес производного объекта b базового класса указателю baselPtr и печатаем целое value, активизируя функцию-элемент getData класса Basel через baselPtr. Аналогично мы присваиваем адрес производного объекта d базового класса указателю base2Ptr и печатаем символ letter, активизируя функцию элемент getData класса Basel через base2Ptr. Этот пример показывает механизм множественного наследования и знакомит с простейшей проблемой неопределенности. Множественное наследование - сложная тема, рассматриваемая более подробно в более серьезных руководствах по С++. Хороший стиль программирования 9.2 Множественное наследование - мощное свойство, но оно может внести в систему сложности. Требуется большая осторожность при проектировании систем для извле -чения выгоды из использования множественного наследования; использовать его не следует, если можно ограничиться простым наследованием. Резюме Одним из ключей к могуществу объектно-ориентированного программирования является достижение повторного использования кодов путем наследования. Программист может указать, что новый класс наследует данные-элементы и функции-элементы ранее определенного базового класса. В этом случае новый класс называется производным классом. При простом наследовании класс порождается только одним базовым классом. При множественном наследовании производный класс наследует нескольким базовым классам (возможно, неродственным). Производный класс обычно добавляет свои собственные данные-элементы и функции-элементы, так что производный класс в общем случае больше своего базового класса. Производный класс более специфичен по своему назначению, более узок, чем его базовый класс,.и представляет меньшую группу объектов. Производный класс не может иметь доступ к закрытым элементам своего базового класса; разрешение доступа нарушило бы инкапсуляцию базового класса. Однако, производный класс может иметь доступ к открытым и защищенным элементам своего базового класса. Конструктор производного класса всегда прежде всего вызывает конструктор своего базового класса для создания элементов базового класса, имеющихся в производном, и задания им начальных значений. Деструкторы вызываются в последовательности, обратной вызовам конструкторов, так что деструктор производного класса вызывается раньше деструктора базового класса. Наследование создает возможность повторного использования кодов, что экономит время разработки и способствует использованию проверенного и отлаженного высококачественного программного обеспечения. Наследование может осуществляться путем использования существующих библиотек классов. Иногда значительная часть программное обеспечение может быть сконструирована из стандартизованных, повторно используемых компонентов точно так же, как сегодня конструируется многое из аппаратного обеспечения. Разработчик производного класса не нуждается в доступе к исходному коду базового класса, но нуждается в доступе к интерфейсу и объектному коду базового класса. Объект производного класса может рассматриваться как объект соответствующего ему базового класса. Однако, обратное неверно. Базовый класс существует в иерархическом взаимоотношении с классом, порожденным от него простым наследованием. Класс может существовать сам по себе. Если этот класс используется в механизме наследования, то он становится либо базовым классом, который снабжает атрибутами и функциями другие классы, либо производным классом, который наследует эти атрибуты и функции.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |