Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / LECS17.DOC
Скачиваний:
44
Добавлен:
16.04.2013
Размер:
151.55 Кб
Скачать

В файле virt_err.Cpp

class B {

public:

virtual void foo (int);

virtual viod foo (double);

};

class D :public B {

public:

void foo (int);

};

int main ( )

{

D d;

B b, *pb = &d;

b.foo(9); //выбирает B::foo(int);

b.foo(9.5); //выбирает B::foo(double);

d.foo(9); //выбирает D::foo(int);

d.foo(9.5); //выбирает D::foo(int);

pb -> foo (9); //выбирает D::foo(int);

pb -> foo (9.5); //выбирает B::foo double);

}

Функция-член базового класса B::foo(int) замещается, а функция-член базового класса B::foo(double) скрыта в производном классе. В инструкции d.foo (9.5) значение с двойной точностью 9.5 преобразуется к целому значению 9. Для вызова скрытой функции члена можно было бы использовать d.B::foo(double).

Объявление идентификатора в области видимости скрывает все объявления этого идентификатора в объемлющих областях видимости. Базовый класс является объемлющей областью видимости для любого их своих произвольных классов. Это правило не зависит от того, были ли имена объявлены как virtual. Ограничения доступа (private, protected) не связаны с выбором функции. Если выбранная функция недоступна, это вызывает ошибку компиляции.

Только нестатические функции-члены могут быть виртуальными. Виртуальность наследуется. Так как функция производного класса автоматически виртуальна, наличие в нем ключевого слова virtual – обычно дело вкуса. Конструкторы не могут быть виртуальными, в отличие от деструкторов. Практически, каждый класс, имеющий виртуальную функцию, должен иметь виртуальный деструктор.

Виртуальные функции позволяют делать выбор на этапе выполнения. Рассмотрим приложение – систему автоматизированного проектирования, в котором должна вычисляться площадь фигур в проекте. Различные фигуры будут наследоваться из базового класса shape (фигура):

В файле shape2.Cpp

class shape { //фигура

public;

Virtual double area () const {return 0;} //площадь

//virtual double area () задает поведение по умолчанию

protected:

double x, y;

};

class rectangle:public shape { //прямоугольник

public:

double area () const { return (height * width); }

private:

double height, width; //высота, ширина

};

class circle: public shape { //окружность

public:

double area () const { return (PI * radius * radius);}

private:

double radius;

};

В этой иерархии классов производные классы соответствуют простым и важным фигурам. Систему легко расширить созданием дополнительных производных классов. За вычисление отвечает производный класс.

Клиентский код, использующий полиморфное вычисление площади выглядит так:

shape* p[N];

…..

for (i = 0; i<N; ++i)

tot_area ();

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

Абстрактные базовые классы

Иерархия типов обычно имеет корневой класс, содержащий некоторое число виртуальных функций. Виртуальные функции обеспечивают динамическую типизацию. Виртуальные функции корневого класса часто являются фиктивными функциями. Они имеют пустое тело в корневом классе, но в производных классах им будет придан конкретный смысл. В С++ для этих целей введена чисто виртуальная функция (pure virtual function). Чисто виртуальная функция – это виртуальная функция, тело которой не определено. Она объявляется внутри класса следующим образом:

virtual прототип_функции = 0

Чисто виртуальная функция используется для того, чтобы отложить выбор реализации функции. В терминологии ООП это называется отложенным методом (deferred method).

Класс, имеющий хотя бы одну чисто виртуальную функцию, называется абстрактным классом (abstract class). Полезно, чтобы корневой тип в иерархии классов был абстрактным классом. Он должен иметь основные общие свойства со своими производными классами, но сам не может использоваться для объявления объектов. Вместо этого он используется для объявления указателей, которые могут иметь доступ к подобъектам, произведенным их абстрактного класса.

Объясним эти идеи, разработав упрощенный вариант экологической модели. Изначально ООП разрабатывалось как методика моделирования с помощью языка моделирования Simula 67. Поэтому многие концепции ООП можно воспринимать как попытку смоделировать конкретную реальность.

Мир в нашем примере включает разные взаимодействующие формы жизни. Абстрактным базовым классом будет living (жизнь). Его интерфейс будет наследоваться разными формами жизни. В качестве архетипического хищника у нас будет выступать лиса, добычей ее будут кролики. Сами кролики питаются травой.

Соседние файлы в папке Лекции