Программирование >>  Аргументация конструирования 

1 ... 96 97 98 [ 99 ] 100 101 102 ... 108


Ответ прост: оба. Класс sleeperSofa паслелует отдельный член Bed::weight и отдельный член Sofa: :weight. Поскольку они оба имеют одно и то хе имя. обращения к we:ght теперь являются двузначными, если только не указывать явно, к какому именно weight мы намерены обратиться. Это демонстрируем ющи]1 фрагмент кода:

jfinclude <iostream.h> void fn()

SleeperSofa ss; cout Зес =

ss. weight неправи.пьно - какой именно вес?

<< \п ;

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

Iinciude <iostrearn. h> void fn{)

SleeperSofa ss;

cout Bee дивана

< :: weight укажем мкой именно вес

<< \n ;

Хот такое решение и устраняет ошибку, указание имени базового класса во внешнем приложении нежелательно: ведь при этом информация о уст-

ройстве класса должна присутствовать за ею пределами. В нашем примере функция fn О должна обладать сведениями о том, что класс sleeper Sofa наследуется от класса Sofa. Такие конфликты имен невозможны при одиночном наследовании, но служат постоянным источником неприятностей при наследовании множественном.

BufUHifOAbHoe наследование

В случае класса SleeperSofa конфликт имен weight является, по сути, небольшим недоразумением. Ведь на самом деле диван-кровать не имеет отдельного веса как кровать, и отдельного веса как диван. Конфликт возник потому, что такая иерархия классов не вполне адекватно описывает реальный мир. Дело в том, что разложение на классы оказалось неполным.

Если немного подумать нал этой проблемой, становится ясно, что и кровать и диван являются частными случаями некоторой более фундаментальной концепции мебели (думаю, можно было предложить нечто еше более фундаментальное, но для нас достаточно ограничиться мебелью). Вес является свойством любой мебели, что показано на рис. 28.2.

Отделение класса Furniture (мебель) должно устранить конфликт имен. Итак,

с чувством глубокого удовлетворения и облегчения, в предвкушении успеха я реализую новую иерархию классов:

tinclude <io3treain.h>

более концепция; этот класс

имеет свойство weight - вес class Furniture {

public:



Furniture о {} rntweiфt;

c:lass : puk)lic cni {

public:

B() {}

void sleep!) {)

c:lass fa : puk)lic rture {

public:

sofa Of} VOidwatchTV () { )

c:lass leeperfa : public Be, public fa

SieeperSofaо {} void foldOut() {}

void fn() {

SleeperSofa ss;

cout вес =

<< ss.weight

\ n ;


Puc. 28.2. Выделение общиств кровати и дивана



М-да.. Не говори гоп , пока не переехав оп - новая иерархия классов совершенно нас угасает, weight остается неоднозначным. Попробуем привести ss к классу Furniture? ttinclude <iostream.h>

void {

fn()

SleeperSofa ss; Furniture* pF; pF = (Furniture*)iss; cout Bee =

<< pF -> weight

<< \n ;

Приведение ss к классу Furniture тоже ничего не дает. Более того, я получил какое-то подозрительное сообщение о том, что приведение SleeperSofa* к классу Furniture* неоднозначно. Да что, в конце концов, творится?

На самом деле все довольно просто. Класс SleeperSofa не наследуется напрямую от класса Furniture. Сначала Furniture наследуют классы Bed и Sofa, а уж потом SleeperSofa наследуется от этих классов. Класс SleeperSofa выглядит в памяти так, как показано на рис. 28.3.

Furniture

Члены Bed (без членов Furniture)

Furniture

Члены Sofa

(без членов Furniture)

Уникальные члены класса SleeperSofa

Часть, наследованная от класса Bed

Часть, наследованная от класса Sofa

Полный -объест SleeperSofa

Рис. 28.3. Расположение класса SleeperSofa в памяти

Как видите, SleeperSofa состоит из класса Bed, за которым в полном составе следует класс Sofa, а после него - уникальные члены класса SleeperSofa. Каждытй из подобъектов класса SleeperSofa имеет свою собственную часть Furniture, поскольку они оба наследуются от этого класса. В результате объекты: класса Sleeper-Sofa содержат два объекта класса Furniture.

Таким образом, становится ясно, что я не сумел создать иерархию, показанную на рис. 28.2. Иерархия наследования, которая бтла создана в результате выполнения пред]дущей программы, показана на рис. 28.4.

SleeperSofa содержит два объекта класса Furniture, что является явной бессмыслицей! Я хочу, чтобы SleeperSofa наследовал только одну копию Furniture и чтобы Bed и Sofa имели к ней доступ. В C++ это достигается виртуальным наследованием, поскольку в этом случае используется ключевое слово virtual.



1 ... 96 97 98 [ 99 ] 100 101 102 ... 108

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика