Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет228/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   224   225   226   227   228   229   230   231   ...   256
Байланысты:
Бьерн Страуструп. Язык программирования С . М Бином, 2011

12.2.2 Иерархии классов 
Рассмотрим моделирование транспортного потока в городе, цель которого достаточно точно 
определить время, требующееся, чтобы аварийные движущиеся средства достигли пункта назначения. 
Очевидно, нам надо иметь представления легковых и грузовых машин, машин скорой помощи, 
всевозможных пожарных и полицейских машин, автобусов и т.п. Поскольку всякое понятие реального 
мира не существует изолированно, а соединено многочисленными связями с другими понятиями, 
возникает такое отношение как наследование. Не разобравшись в понятиях и их взаимных связях, мы 
не в состоянии постичь никакое отдельное понятие. Также и модель, если не отражает отношения 
между понятиями, не может адекватно представлять сами понятия. Итак, в нашей программе нужны 
классы для представления понятий, но этого недостаточно. Нам нужны способы представления 
отношений между классами. Наследование является мощным способом прямого представления 
иерархических отношений. В нашем примере, мы, по всей видимости, сочли бы аварийные средства 
специальными движущимися средствами и, помимо этого, выделили бы средства, представленные 
легковыми и грузовыми машинами. Тогда иерархия классов приобрела бы такой вид:
движущееся средство
легковая машина
аварийное средство
грузовая машина 
полицейская машина
машина скорой помощи
пожарная машина 
машина с выдвижной лестницей 
Здесь класс Emergency представляет всю информацию, необходимую для моделирования аварийных 
движущихся средств, например: аварийная машина может нарушать некоторые правила движения, она 
имеет приоритет на перекрестках, находится под контролем диспетчера и т.д. 
На С++ это можно задать так: 
class Vehicle { /*...*/ }; 
class Emergency { /* */ }; 
class Car : public Vehicle { /*...*/ }; 
class Truck : public Vehicle { /*...*/ }; 
class Police_car : public Car , public Emergency { 


Бьерн Страуструп.
Язык программирования С++ 
 
317 
//... 
}; 
class Ambulance : public Car , public Emergency { 
//... 
}; 
class Fire_engine : public Truck , Emergency { 
//... 
}; 
class Hook_and_ladder : public Fire_engine { 
//... 
}; 
Наследование - это отношение самого высокого порядка, которое прямо представляется в С++ и 
используется преимущественно на ранних этапах проектирования. Часто возникает проблема выбора: 
использовать наследование для представления отношения или предпочесть ему принадлежность. 
Рассмотрим другое определение понятия аварийного средства: движущееся средство считается 
аварийным, если оно несет соответствующий световой сигнал. Это позволит упростить иерархию 
классов, заменив класс Emergency на член класса Vehicle: 
движущееся средство (Vehicle {eptr}) 
легковая машина (Car)
грузовая машина (Truck) 
полицейская машина (Police_car)
машина скорой помощи (Ambulance) 
пожарная машина (Fire_engine) 
машина с выдвижной лестницей (Hook_and_ladder) 
Теперь класс Emergency используется просто как член в тех классах, которые представляют аварийные 
движущиеся средства: 
class Emergency { /*...*/ }; 
class Vehicle { public: Emergency* eptr; /*...*/ }; 
class Car : public Vehicle { /*...*/ }; 
class Truck : public Vehicle { /*...*/ }; 
class Police_car : public Car { /*...*/ }; 
class Ambulance : public Car { /*...*/ }; 
class Fire_engine : public Truck { /*...*/ }; 
class Hook_and_ladder : public Fire_engine { /*...*/ }; 
Здесь движущееся средство считается аварийным, если Vehicle::eptr не равно нулю. "Простые" 
легковые и грузовые машины инициализируются Vehicle::eptr равным нулю, а для других Vehicle::eptr 
должно быть установлено в ненулевое значение, например: 
Car::Car()
// 
конструктор Car 

eptr = 0; 

Police_car::Police_car() // 
конструктор Police_car 

eptr = new Emergency; 

Такие определения упрощают преобразование аварийного средства в обычное и наоборот: 
void f(Vehicle* p) 

delete 
p->eptr; 
p-
>eptr = 0; // больше нет аварийного движущегося средства 
//... 
p->eptr = new Emergen
cy; // оно появилось снова 

Так какой же вариант иерархии классов лучше? В общем случае ответ такой: "Лучшей является 


Бьерн Страуструп.
Язык программирования С++ 
 
318 
программа, которая наиболее непосредственно отражает реальный мир". Иными словами, при выборе 
модели мы должны стремиться к большей ее"реальности", но с учетом неизбежных ограничений, 
накладываемых требованиями простоты и эффективности. Поэтому, несмотря на простоту 
преобразования обычного движущегося средства в аварийное, второе решение представляется 
непрактичным. Пожарные машины и машины скорой помощи – это движущиеся средства специального 
назначения со специально подготовленным персоналом, они действуют под управлением команд 
диспетчера, требующих специального оборудования для связи. Такое положение означает, что 
принадлежность к аварийным движущимся средствам - это базовое понятие, которое для улучшения 
контроля типов и применения различных программных средств должно быть прямо представлено в 
программе. Если бы мы моделировали ситуацию, в которой назначение движущихся средств не столь 
определенно, скажем, ситуацию, в которой частный транспорт периодически используется для доставки 
специального персонала к месту происшествия, а связь обеспечивается с помощью портативных 
приемников, тогда мог бы оказаться подходящим и другой способ моделирования системы. 
Для тех, кто считает пример моделирования движения транспорта экзотичным, имеет смысл сказать, 
что в процессе проектирования почти постоянно возникает подобный выбор между наследованием и 
принадлежностью. Аналогичный пример есть в $$12.2.5, где описывается свиток (scrollbar) - 
прокручивание информации в окне. 


Достарыңызбен бөлісу:
1   ...   224   225   226   227   228   229   230   231   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет