Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекцій.doc
Скачиваний:
15
Добавлен:
03.11.2018
Размер:
1.12 Mб
Скачать

8.2 Чисті віртуальні функції. Абстрактні класи.

Чиста вiртуальна функцiя-член - це прототип функцiї, для якого не потрiбне визначення в протоколi класу.Cинтаксично чиста віртуальна функція задається так:

virtal<тип><iм'я>(сигнатура)=0;

Клас, який мiстить чисті вiртуальнi функцiї називається абстрактним.

Приклад:

class AbstractClass {

public:

virtual void f1(void);

virtual void f2(void)=0;

//...};

Специфiка абстрактного класу полягає в тому, що вiн не може мати екземплярiв. При оголошенні AbstractClass my; буде помилка на етапі компіляції. Для того, щоб використовувати абстрактні класи, необхідно визначити похідний від нього клас, в якому чиста віртуальна функція оголошується як звичайна віртуальна функція. Причому в цьому випадку вона повинна мати тіло. Розглянемо, наприклад, такий клас:

class MyClass:public AbstractClass{

public;

virtual void f2(void);

//...

}

void MyClass::f2(void)

{\\тіло}

Звернемо увагу на те, що у класi MyClass f2() є вже звичайною вiртуальною функцiєю(а не чистою), отже повинне бути її визначення(в даному випадку-за межами формального опису класу). Тодi, очевидно, можемо описати екземпляр класу MyClass.

Чиста вiртуальна функцiя може вiльно використовуватись в протоколi абстрактного класу.

Похідний клас, який не визначає всi чистi вiртуальнi функцiї базового класу, також являється абстрактним. Напишемо, наприклад, програму, яка манiпулює з множинами без врахування типів множин:

Приклад:

class TElem;

typedef TElem*PTElem;

typedef PTElem*PPTElem;

class TSet;

typedef TSet*PTset;

class TSet{

private:

int max; //-кiлькiсть елементiв

int index;

PPTElem set;

protected:

virtual int CompareElem(pTElem P1,/PTElem P2)=0;

public:

TSet(int n)

{max=n;index=0;

set=new PTElem[n];}

virtual ~TSet( )

{delete[ ]set;}

void AddElem(PTElem p);

int HasElem(PTElem p);

};

void TSet::AddElem(PTElem P)

{if (set==null)

{cout<<"\n Error";

exit(1);}

if (index>=max){

cout<<"\n Error,Set linut excuded";

exit(1);}

set [index]=p;

++index;}

int TSet::HasElem(PTElem P)

{if (set==null)return0;

for(inti=0;i<index;i++)

if (CompareElem(P'set[i])==0)

return1;return0;

}

Запишемо визначений клас TSet у файл Set.h:

# include"set.h"

class TElem {

private:

char*sp;

public:

TElem(const char*s)

{sp=strdup(s);}

virtual~TElem( ){delete sp;}

virtual const char*GetString(void)

{return sp;} };

class Myset:public TSet{

protected:

virtual int CompareElem(PTElemP1;PTElemP2);

public:

TMySet(int n):TSet(n){ }

};

main( )

{TMyset thirties(12);

thurties.AddElem(new Telem("Sep"));

thurties.AddElem(new TElem("Jan"));

thurties.AddElem(new Telem("Feb"));

thurties.AddElem(new TElem("Mar"));

Test("Jan",& thurties);

return 0;}

// повідомляє, чи належить рядок s множині setp

void Test(const char*,PTSet setp)

{ TElem testElem(s);

if(set=>HasElem(& testElem)

cout <<"yes";

else cout<<"No";}

Переваги використання абстрактних класів:

- Модуль Set можна скомпiлювати ранiше i зберегти в бiблiотецi класу;

- Очевидно, що клас TSET може використовувати iншi програми, причому повторно компiлювати файл Set не потрiбно;

- При проектуваннi абстрактних класiв бажано розмiщувати в них кiлька вiртуальних функцiй членiв на випадок, коли вони можуть бути корисними;

- Вiртуальнi деструктори.