Программирование >>  Унарные и бинарные операторы 

1 ... 26 27 28 [ 29 ] 30 31 32 ... 37


200 Глава lO. Наследование

ПО ИХ образу и подобию объекты напоминают платоновские идеи и их несовершенные воплощения? Разница в том, что объекты С++, о которых мы до сих пор знали, - скорее точные, а не приблизительные копии идей (классов). Но в С++, как вы, наверное, уже заметили, есть все, в том числе и абстрактные платоновские идеи.

Представим себе различных животных: кошек, собак, свиней и т. д. Каждое животное издает определенные звуки: собака лает, кошка мяукает, свинья хрюкает. И в соответствующих объектах должны быть функции, имитирующие эти крики. Но чтобы автоматически вызывать нужную функцию, как это мы делали в предыдущем разделе, необходимо не только одинаково назвать эти функции в разных классах (скажем, voice), но и сделать все эти классы производными от чего-то высшего, например от класса animal (животное). В этом классе тоже должна быть функция voice, перед объявлением которой стоит слово virtual. Но как кричит животное ? Каким образом определить такую функцию?

Проще всего оставить такую функцию пустой:

class animal { public:

virtual void voice(){}:

Ho это не очень красиво, ведь объекты, которые ничего не делают, никому не нужны. Поэтому в С++ решено в таких случаях быть честными до конца и прямо указывать, что данный класс - фиктивный, саздаиный только для формального построения настоящих производных классов и вызова собственных функций, соответствующих природе объекта.

Делается это с помощью особой записи функции:

class animal { public:

virtual void voice()=0:

Идеи и вещи 201

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

Программа, показанная в листинге 10.9, использует абстрактный базовый класс animal для создания двух обычных классов dog и cat. Заметим, что в классах, производных от абстрактного, если они, конечно, хотят порождать объекты, нужно определить функсши с тем же именем, что у чисто виртуальной функции базового класса. Если этого не сделать, класс унаследует функцию базового класса и автоматически станет абстрактным. А это приведет к тому, что при создании объекта этого класса компилятор выдаст сообщение об ошибке. Выходит, абстрактные базовые классы не так уж абстрактны, раз они помогают контролировать правильность программы.

Листинг 10.9

#i ncl ude <:iostream> using namespace std: class animal{ public:

virtual void voice()=0: }:

class dog : public animal { public:

void voice(){cout Ab! end!:} }:

class cat : public animal {

void voice(){cout Мяу! endl:}

int main(){ animal *a[2]:

a[D]=new dog a[l]=new cat a[0]->voice():

Ab!

проАОЛжение



ГЛАВА 11 Шаблоны


Листинг 10.9 (продолжение)

a[l]->voice(); Мяу! return 0:

Завершим этот раздел замечанием, которое вполне уместно было бы сделать еще в разделе Изменчивость и отбор . Занимаясь вызовом правильной функции, мы опять забыли о создании и упичтожстп! объектов. Представим себе, что объект производного класса создается оператором new, причем его адрес оказывается в указателе на базовый класс:

class base { virtual f():

class der : public base { }:

base *p: p= new der:

delete p: вызывается деструктор base!

Если f() - единственная виртуальная функция в базовом классе, то при уничтожении обт>екта der вызовется деструктор -based, что опасно, когда в производном классе выделяется дополнительная память, о которой этот деструктор ничего не знает. Вывод прост: деструктор базового класса всегда должен быть виртуальным. Тогда инструкция delete р вызовет сначала деструктор производного, а затем уже деструктор базового класса, каждый из них освободит ту память, за которую отвечает, и все в результате будет хорошо.

Задача 10.3. Пусть р - указатель на производны!! класс. Должен ли деструктор базового класса быгь виртуальным, чтобы правильно освобождалась память после удаления объекта инструкцией delete р?



Шаблоны функций

Этих шаблонов Тюбик наделал несколько штук. Если у малышки были голубые глаза и светлые волосы, он брал шаблон с голубыми глазами и светлыми волосами, добавляя немножечко схол-ства, и портрет был готов. Если же у малышки были волосы и глаза темные, то у Тюбика и на этот случай имелся шаблон.

Н. Носов,

* Приключения Нез}шйки и его друзей*

В разделе Функции-тезки главы 5 мы заготовили две одноименные функции niin3() для работы с объектами разной природы. Оказывается, в С++ есть enic один способ справиться с разнообразием аргументов - шаблоны. Вместо того чтобы описывать каждую функцию, можно создать один шаблон, и компилятор, проанализировав аргументы, сам создаст с помощью шаблона нужную функцию.

В программе из листинга 11.1 набор функций, вычисляющих минимальные значения переменных, задается шаблоном template <typename Т>, где Т обозначает тип аргументов и возвращаемых функцией значений (ключевое слово typename переводится как имя типа ).

Листинг 11.1

#include <iostreara> using namespace std:

Вместо буквы Т в шаблоне можно поставить любую другую букву или слово.

Шаблоны классов 205

template <typename Т> Т min3(T X. Т у. Т z){ Т min=x:

if(y < min) min=y: if(z < min) min=z: return min:

int main(){

int a=2.b=5.c=-5:

cout min3(a*c.b.c) endl:

cout min3(0.03*a.10.0.5.0) endl:

return 0:

Встретив вызов функции miпЗ(a*c. b.с), компилятор обнаружит целочисленные аргументы и, пользуясь шаблоном, сам создаст нужную функцию. Компилятор не ошибется, если все три аргумента будут одного тина. Если же они окажутся разными, компилятор не найдет подходящего шаблона и выдаст сообщение об ошибке.

Шаблоны классов

Он не просто нереален (это слово, в сущности, приложимо ко всему в человеческом мире). Нет слов, чтобы описать степень его нереальности. Это нагромождение одного несуществования на другое, воздуптый замок, фундаментом которого служит пропасть.

В. Пелевин, Generation /7 Можно сказать, что классы в С++ нереальны - в том смысле, что их нельзя непосредственно увидеть (например, вывести на экран как какие-то переменные). Видимы в С++ только объекты, созданные по образу и подобию классов. Оказьшается, цепочку несущество-



1 ... 26 27 28 [ 29 ] 30 31 32 ... 37

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