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



бет108/124
Дата16.07.2016
өлшемі3.27 Mb.
#204081
түріКнига
1   ...   104   105   106   107   108   109   110   111   ...   124

12.2.2 Иерархии классов


Рассмотрим моделирование транспортного потока в городе, цель которого

достаточно точно определить время, требующееся, чтобы аварийные движущиеся

средства достигли пункта назначения. Очевидно, нам надо иметь

представления легковых и грузовых машин, машин скорой помощи,

всевозможных пожарных и полицейских машин, автобусов и т.п.

Поскольку всякое понятие реального мира не существует изолированно,

а соединено многочисленными связями с другими понятиями,

возникает такое отношение как наследование. Не разобравшись в понятиях

и их взаимных связях, мы не в состоянии постичь никакое отдельное

понятие. Также и модель, если не отражает отношения между

понятиями, не может адекватно представлять сами понятия. Итак, в

нашей программе нужны классы для представления понятий, но этого

недостаточно. Нам нужны способы представления отношений между классами.

Наследование является мощным способом прямого представления

иерархических отношений. В нашем примере, мы, по всей видимости,

сочли бы аварийные средства специальными движущимися средствами

и, помимо этого, выделили бы средства, представленные легковыми и

грузовыми машинами. Тогда иерархия классов приобрела бы такой вид:

движущееся средство

легковая машина аварийное средство грузовая машина

полицейская машина машина скорой помощи пожарная машина

машина с выдвижной лестницей

Здесь класс Emergency представляет всю информацию, необходимую для

моделирования аварийных движущихся средств, например: аварийная

машина может нарушать некоторые правила движения, она имеет

приоритет на перекрестках, находится под контролем диспетчера

и т.д.


На С++ это можно задать так:
class Vehicle { /*...*/ };

class Emergency { /* */ };

class Car : public Vehicle { /*...*/ };

class Truck : public Vehicle { /*...*/ };

class Police_car : public Car , public Emergency {

//...


};

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 Emergency; // оно появилось снова

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

"Лучшей является программа, которая наиболее непосредственно отражает

реальный мир". Иными словами, при выборе модели мы должны стремиться

к большей ее"реальности", но с учетом неизбежных ограничений,

накладываемых требованиями простоты и эффективности. Поэтому,

несмотря на простоту преобразования обычного движущегося средства в

аварийное, второе решение представляется непрактичным.

Пожарные машины и машины скорой помощи - это

движущиеся средства специального назначения со специально

подготовленным персоналом, они действуют под управлением команд

диспетчера, требующих специального оборудования для связи. Такое

положение означает, что принадлежность к аварийным движущимся средствам -

это базовое понятие, которое для улучшения контроля типов и

применения различных программных средств должно быть прямо

представлено в программе. Если бы мы моделировали ситуацию, в которой

назначение движущихся средств не столь определенно,

скажем, ситуацию, в которой частный транспорт периодически используется

для доставки специального персонала к месту происшествия, а связь

обеспечивается с помощью портативных приемников, тогда мог бы

оказаться подходящим и другой способ моделирования системы.

Для тех, кто считает пример моделирования движения транспорта

экзотичным, имеет смысл сказать, что в процессе проектирования

почти постоянно возникает подобный выбор между наследованием

и принадлежностью. Аналогичный пример есть в $$12.2.5, где

описывается свиток (scrollbar) - прокручивание информации в окне.





Достарыңызбен бөлісу:
1   ...   104   105   106   107   108   109   110   111   ...   124




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

    Басты бет