Здавалка
Главная | Обратная связь

Чисто виртуальные функции



Слово "чисто" – в данном случае используется в контексте "пусто". Иными словами, чисто виртуальная функция - функция пустая. Синтаксис создания её таков:

class A { public: //чисто виртуальная функция virtual void v_function()=0; };

Как видите, все отличие только в том, что появилась конструкция «=0», которая называется «чистый спецификатор». Чисто виртуальная функция абсолютно ничего не делает и недоступна для вызовов. Ее назначение – служить основой (если хотите, шаблоном) для замещающих функций в производных классах.

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

Примечание:Приведем пример. Все животные в своем поведении имеют такие функции, как «есть», «пить», «спать», «издавать звук». Имеет смысл определить базовый класс, в котором сразу объявить все эти функции и сделать их чисто виртуальными. А потом из этого класса выводить классы, описывающие конкретных животных (или виды), со своим специфичным поведением. А базовый класс при этом действительно получается абстрактным. Ведь он не описывает никакое более-менее конкретное животное (даже вид животных). Это может быть и рыба и птица....

По сравнению с обычными классами, абстрактные классы пользуются «ограниченными правами».

  • Как и всякий класс, абстрактный класс может иметь явно определенный конструктор. Из конструктора можно вызывать методы класса. Но обращение из конструктора к чистым виртуальным функциям приведут к ошибкам во время выполнения программы.
  • Как уже говорилось, невозможно создать объект абстрактного класса.
  • Абстрактный класс нельзя применять для задания типа параметра функции, или в качестве типа возвращаемого значения.
  • Его нельзя использовать при явном приведении типов. Зато можно определять ссылки и указатели на абстрактные классы.

Пример.

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

#include <iostream>#include <string.h>using namespace std; //абстрактный базовый классclass Animal{ public: //кличка животного char Title[20]; //простой конструктор Animal(char *t){ strcpy(Title,t); } //чисто виртуальная функция virtual void speak()=0; }; //класс лягушкаclass Frog: public Animal{ public: Frog(char *Title): Animal(Title){}; virtual void speak(){ cout<<Title<<" say "<<"\'kwa-kwa\'\n"; }}; //класс собакаclass Dog: public Animal{ public: Dog(char *Title): Animal(Title){}; virtual void speak(){ cout<<Title<<" say "<<"\'gav-gav\'\n"; }}; //класс кошкаclass Cat: public Animal{ public: Cat(char *Title): Animal(Title){}; virtual void speak(){ cout<<Title<<" say "<<"\'myau-myau\'\n"; }}; //класс левclass Lion: public Cat{ public: Lion(char *Title): Cat(Title) {}; /*virtual void speak(){ cout<<Title<<" say "<<"\'rrr-rrr\'\n"; }*/ /*virtual int speak(){ cout<<Title<<" say "<<"\'rrr-rrr\'\n"; return 0; }*/ virtual void speak(int When){ cout<<Title<<" say "<<"\'rrr-rrr\'\n"; }}; void main (){ // объявим массив указателей на базовый класс Animal // и сразу его заполним указателями, создавая объекты // cписок животных Animal *animals[4] = {new Dog("Bob"), new Cat("Murka"), new Frog("Vasya"), new Lion("King")}; for(int k=0; k<4; k++) animals[k]->speak();}

В качестве базового класса создан абстрактный класс Animal. Он имеет единственный член Title, описывающий кличку животного. В нем есть явно определенный конструктор, который присваивает животному его «имя». И, единственная чисто виртуальная функция speak(), которая описывает, какие звуки издает животное.

От этого класса отнаследованны все остальные. Кроме одного. Класс «лев» порожден от класса «кошка» (львы это тоже кошки). Это сделано для демонстрации тонкостей применения виртуальных функций. Но об этом классе немного позже.

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

В основном теле программы объявлен массив animals[4] указателей типа Animal*. И сразу же созданы динамические объекты классов и заполнен массив указателей. А в цикле for() по указателю просто вызывается виртуальная функция speak().

Результат работы программы таков:

Bob say 'gav-gav'Murka say 'myau-myau'Vasya say 'kwa-kwa'King say 'rrr-rrr'

Теперь обратимся к описанию класса Lion (лев). В нем вместо одной виртуальной функции speak() содержится сразу три. Две из них закомментированы.

Если вы закомментируете первую функцию, а раскомментируете вторую, то сможете проверить вариант, когда производится попытка соорудить виртуальную замещающую функцию с другим типом возвращаемого значения. В данном случае вторая (неправильная) функция возвращает тип int вместо типа void, который был у функции speak()в базовом классе. Попробуйте скомпилировать программу и произойдет ошибка на этапе компиляции.

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

Bob say 'gav-gav'Murka say 'myau-myau'Vasya say 'kwa-kwa'King say 'myau-myau'

Лев у нас уже не рычит, а мяукает. Это потому, что работает уже совсем другая функция! То есть, раз в данном классе нет правильно определенной виртуальной функции, то по указателю вызывается виртуальная функция speak() из базового класса. А в нашем случае базовым для класса Lion является класс Cat. Вот лев и замяукал.

Предыдущая Оглавление Следующая
Предыдущая Оглавление Следующая






©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.