class Bed : public Furniture
{
public :
Bed( int weight ) : Furniture( weight ) { }
void sleep( ) { cout << "Спим" << endl ; }
} ;
class Sofa : public Furniture
{
public :
Sofa( int weight ) : Furniture( weight ) { }
void watchTV( ) { cout << "Смотрим телевизор" << endl ; }
} ;
/* SleeperSofa — диван-кровать */
class SleeperSofa : public Bed , public Sofa
{
public :
SleeperSofa( int weight ) : Sofa( weight ) , Bed( weight ) { }
void foldOut( ) { cout << "Раскладываем диван-кровать"
<< endl ; }
} ;
int main( int nNumberofArgs , char* pszArgs[ ] )
{
/* печать кириллицы, если Вы не установите программки gccrus.exe и g++rus.exe */
setlocale ( LC_ALL , ".1251" ) ;
SleeperSofa ss( 10 ) ;
/* Section 1 — неоднозначность: Furniture::Sofa или Furniture::Bed? */
/*
cout << "Beс = "
<< ss.weight
<< endl ;
*/
/* Section 2 — Один из способов устранения неоднозначности */
SleeperSofa* pSS = &ss ;
Sofa* pSofa = ( Sofa* )pSS ;
Furniture* pFurniture = ( Furniture* )pSofa ;
cout << "Beс = "
<< pFurniture -> weight
<< endl ;
/* Пауза для того, чтобы посмотреть на результат работы программы */
system( "PAUSE" ) ; return 0 ;
}
_________________
302 стр. Часть 5. Полезные особенности
М-да... "Не говори "гоп", пока не переехал Чоп" — новая иерархия классов совершенно нас не спасает, weight остаётся неоднозначным. Попробуем привести ss к классу Furniture.
#include
void fn( )
{
SleeperSofa ss ;
Furniture* pF ;
pF = ( Furniture* )&ss ;
cout << "Beс = "
<< pF -> weight
<< "\n" ;
} ;
Приведение ss к классу Furniture тоже ничего не даёт. Более того, я получил какое-то подозрительное сообщение о том, что приведение SleeperSofa* к классу Furniture* неоднозначно. Да что, в конце концов, творится?
На самом деле всё довольно просто. Класс SleeperSofa не наследуется напрямую от класса Furniture. Сначала Furniture наследуют классы Bed и Sofa, а уж потом SleeperSofa наследуется от этих классов. Класс SleeperSofa выглядит в памяти так, как показано на рис. 26.3.
Рис. 26.3. Расположение класса SleeperSofa в памяти
Как видите, SleeperSofa состоит из класса Bed, за которым в полном составе следует класс Sofa, а после него — уникальные члены класса SleeperSofa. Каждый из подобъектов класса SleeperSofa имеет свою собственную часть Furniture, поскольку они оба наследуются от этого класса. В результате объекты класса SleeperSofa содержат два объекта класса Furniture.
Таким образом, становится ясно, что я не сумел создать иерархию, показанную на рис. 26.2. Иерархия наследования, которая была создана в результате выполнения предыдущей программы, показана на рис. 26.4.
SleeperSofa содержит два объекта класса Furniture — явная бессмыслица! Необходимо, чтобы SleeperSofa наследовал только одну копию Furniture и чтобы Bed и Sofa имели к ней доступ. В С++ это достигается виртуальным наследованием, поскольку в этом случае используется ключевое слово virtual.
_________________
303 стр. Глава 26. Множественное наследование
Рис. 26.4. Результат попытки создания иерархии классов
«В данном случае произошло смешение терминов, однако необходимо принять к сведению, что виртуальное наследование не имеет ничего общего с виртуальными функциями!»
[Советы]
Вооружённый новыми знаниями, я возвращаюсь к классу SleeperSofa и реализую его так, как показано ниже.
//
/* VirtualInheritance — виртуальное */
/* наследование позволяет */