Virtual int CompareElem(PElem p1,PElem p2)

{

return strcmp(p1->GetString(),p2->GetString());

};

public:

Myset(int n):Set(n){}

};

void Test(const char*s,PSet setp)

{Element testElem(s);

if(setp->HasElem(& testElem))

cout<<"yes";

else cout<<"No";}

Main()

{Myset t(4);

t.AddElem(new Element("Sep"));

t.AddElem(new Element("Jan"));

t.AddElem(new Element("Feb"));

t.AddElem(new Element("Mar"));

Test("Jan",&t);

return 0;}

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

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

a клас Set може використовувати інші програми, причому повторно компілювати файл Set не потрібно;

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

a наявність віртуальних деструкторів.

Віртуальні деструктори

Деструктори, на відміну від конструкторів, можуть бути віртуальними. Синтаксично вони задаються, як і звичайні віртуальні функції, за допомогою ключового слова virtual. Віртуальні деструктори використовуються у випадку, коли в деякому класі необхідно знищити об'єкти похідного класу, на які посилаються покажчики на базовий клас. Розглянемо приклад:

class Base{

private:

char*sp1;

public:

Base(const char*s)

{sp1=strdup(s);}

virtual ~Base()

{delete sp1;}};

class Derived::public Base{

private:

char*sp2;

public:

Derived(const char*s1,const char*s2):Base(s1)

{sp2=strdup(s2);}

virtual~Derived()

{delete sp2;}};

Base*pbase;

pbase=new Derived("string1","string2");

Delete pbase; //s1-знищився,s2-залишився.

Якщо б у цьому прикладі деструктори не були віртуальними, то при виході з області видимості об'єкта класу Derived, на який указує покажчик pbase, викликався б лише деструктор класу Base, тобто копія рядка string2 залишилася б у пам'яті. Якщо ж деструктори оголошені як віртуальні, то в даній ситуації буде викликаний спочатку деструктор похідного класу, а потім – базового.

Посилання як засіб для реалізації поліморфізму

Для реалізації поліморфізму в С++, крім покажчиків, можна використовувати й посилання. Розглянемо приклад:

#include "form.h"

Main

{circle c1;

Line l1,l2;

shape & pic0=c1

shape & pic1=l1;

shape & pic2=l2;

pic0.Draw();

pic1.Draw();

pic2.Draw();}

У цьому прикладі кожен виклик функції Draw() приводить до зображення відповідної фігури.

При передаванні параметрів віртуальним функціям може виникнути помилка. Виникає питання: коли здійснюється контроль за помилками при передаванні параметрів? Адже конкретна реалізація віртуальної функції зв'язується з об'єктом на етапі виконання програми. Що стосується С++, то контроль за помилками при передаванні параметрів віртуальним функціям здійснюється на етапі компіляції, а не виконання програми, тому що сигнатури віртуальних функцій мають строго збігатися.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: