1 / 49

Виртуални функции и виртуални класове

Виртуални функции и виртуални класове. Полиморфизъм. Виртуални функции Полиморфизмът е свойство на член-функциите и се реализира с виртуални функции .

iokina
Download Presentation

Виртуални функции и виртуални класове

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции • Полиморфизмът е свойство на член-функциите и се реализира с виртуални функции. • Той се състои в осигуряване възможността генерираният код да се държи по различен начин в зависимост от условия, определяни по време на изпълнението на програмата. • Идеята на тези функции се основава на вида на свързването им: • статично или ранносвързване • динамично или късно свързване

  2. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции • Статичното свързване на типа на обекта с извикваната член-функция става по време на компилацията и не се променя при изпълнение на програмата. • Kонфликтът между имената на наследените и собствените методи от един и същ тип и с едни и същи параметри се разрешава също по време на компилация чрез правилото на локалния приоритет и чрез явно посочване на класа, към който принадлежи методът. • Свързващият редактор замества имената на извикваните функции с конкретните им адреси.

  3. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Пример илюстриращ статично или ранно свързване #include <iostream.h> 1/2 class point { protected: int x,y; public: point(int a=0,int b=0) { x=a; y=b; } void out() {cout<<”точка:”<<x<<” “<<y<<”\n”; } }; class pointcol:public point { short color; public: pointcol(int a=0,int b=0,short cl=1):point(a,b) { color=cl; } void out() {cout<<”оцветена точка:”<<x<<” “<<y<<” с цвят:”<<color<<”\n”; } };

  4. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Пример илюстриращ статично или ранно свързване void main() 2/2 { point p(3,5),*adp=&p; pointcol pc(8,6,2),*adpc=&pc; adp->out(); //извиква се out на point adpc->out();//извиква се out на pointcol adp=adpc; adp->out(); //но adp е point по време на компилация adpc->out(); } По време на изпълнението точка:3 5 оцветена точка:8 6 с цвят:2 точка:86 оцветена точка:8 6 с цвят:2 Извиква се out() от класа point

  5. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Пример илюстриращ статично или ранно свързване Ако искаме след свързването на adp с адреса на pc да се изпълни член-функцията out() на pointcol void main() { point p(3,5),*adp=&p; pointcol pc(8,6,2),*adpc=&pc; adp=adpc; adp->out(); adpc->out(); ((pointcol*)adp)->out(); } точка:86 оцветена точка:8 6 с цвят:2 оцветена точка:8 6 с цвят:2 Извиква се out() от класа point Извиква се out() от класа pointcol след явно преобразуване

  6. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции • Статичното свързване предполагапо време на създаването на класа да се предвидят възможните обекти, чрез които ще се викат член-функциите му. • При сложни йерархии от класове това е не само трудно, но и понякога невъзможно. • Динамично свързване на типа на обекта с извикваната член-функция е по време на изпълнение на програмата. • При него не се налага проверка на типа.

  7. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции • Динамично свързване • При извикването на функция се задава само името, но не и конкретния адрес на прехода. • Или по време на изпълнение се дава възможността за промяна на връзките между имена и адреси. • Текстовете на програмите се опростяват, а промени се налагат много по-рядко.

  8. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции • Динамично свързване • Кодът се усложнява и се забавя процеса на изпълнение на програмата. • Наличието на двата механизма на свързване – статично и динамично, дава възможност на програмиста да се възползва от положителните им страни. • Прилагането на механизма на късното свързване се осъществява върху специални член-функции на класове, наречени виртуални член-функции или само виртуални функции (преддекларацията им се поставя запазената дума virtual ).

  9. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Пример илюстриращ динамично или късно свързване #include <iostream.h> 1/2 class point { protected: int x,y; public: point(int a=0,int b=0) { x=a; y=b; } virtualvoid out() {cout<<”точка:”<<x<<” “<<y<<”\n”; } }; class pointcol:public point { short color; public: pointcol(int a=0,int b=0,short cl=1):point(a,b) { color=cl; } void out()//също е virtual(с или без служебна дума) { cout<<”оцветена точка:”<<x<<” “<<y<<”с цвят:”<<color<,”\n”;} };

  10. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Пример илюстриращ динамично или късно свързване void main() 2/2 { point p(3,5),*adp=&p; pointcol pc(8,6,2),*adpc=&pc; adp->out(); //извиква се out на point adpc->out();//извиква се out на pointcol adp=adpc; adp->out(); //adp е pointcol по време на изпълнение adpc->out(); } По време на изпълнението точка:3 5 оцветена точка:8 6 с цвят:2 оцветена точка:8 6 с цвят:2 оцветена точка:8 6 с цвят:2

  11. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Извод • Определянето на извикваната функция е в зависимост от типа на обекта, към който сочи указателят, а не от класа към който е указателят. • Указател на базовия клас (adp) се използва за извикване на член-функции на производния клас вместо едноименните (предефинирани) функции на базовия (в случай, когато последните са virtual). • Невъзможно е: adpc=adp (съобщение за грешка).

  12. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции #include <iostream.h> 1/2 class point { int x, y; public: point(int a=0, int b=0) { x = a; y = b; } virtual void specific() { cout << “Точка: “; } void out() { specific(); cout << x << “ “ << y << “\n”;} }; class pointcol : public point { short color; public: pointcol(int a=0, int b=0, short c=1) : point(a,b) { color = c; } virtual void specific() { cout << “Оцветена точка с цвят: “ << color << “,”; } }; Виртуална функция за специфичните действия на класа Виртуална функция за специфичните действия на класа

  13. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции void main() 2/2 { point p(3,5), *adp; adp = &p; pointcol pc(5,9,5), *adpc; adpc = &pc; p.out(); pc.out(); adp -> out(); adpc -> out(); adp = adpc; adp -> out(); adpc -> out(); } Извиква се out() от клас point, която извиква specific() Точка: 3 5 Оцветена точка с цвят: 5,5 9 Точка: 3 5 Оцветена точка с цвят: 5,5 9 Оцветена точка с цвят: 5,5 9 Оцветена точка с цвят: 5,5 9

  14. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции извикване на член-функция на базата на динамичния тип на викащия обект #include <iostream.h> class animal { protected: int age; public: animal(): age(1) { } virtual void speak() { cout<<”Animal speaks.\n”; } }; class dog:public animal { public: void speak() { cout<<”Baow.\n”; } }; class cat:public animal { public: void speak() { cout<<”Meow.\n”; } }; class pig:public animal { public: void speak() { cout<<”Grouch.\n”; } }; speak() ще се извиква в зависимост от това къде сочи указателя в момента на изпълнение

  15. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции void main() { animal *a[4],*ptr; int choice; for(int i=0;i<4;i++) { cout<<”(1)dog (2)cat (3)pig:”; cin>>choice; switch(choice) { case 1: ptr=new dog; break; case 2: ptr=new cat; break; case 3: ptr=new pig; break; default:ptr=new animal; } a[i]=ptr; } for(i=0;i<4;i++) a[i]->speak(); } масив от указатели към базов клас и указател за връзка с обектите ptr се свързва с обектите по време на изпълнение (1)dog(2)cat(3)pig:1 (1)dog(2)cat(3)pig:2 (1)dog(2)cat(3)pig:3 (1)dog(2)cat(3)pig:4 Baow. Meow. Grouch. Animal speaks.

  16. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Някои правила • При наличие на виртуална функция – деструкторът трябва да е виртуален. • Конструкторът не може да бъде виртуален. • Ако е предефинирана виртуална функция, но с друг брой на параметрите, то това е друга функция и няма динамично свързване с нея. • Възможно е виртуална функция да се дефинира извън клас. Тогава заглавието й не започва със запазената дума virtual, т.е. запазената дума virtual може да се среща само в тялото на клас.

  17. Виртуални функции и виртуални класове Полиморфизъм. Виртуални функции Някои правила • Ако в даден клас е декларирана виртуална функция, декларираните член-функции със същия прототип (име, параметри и тип на върнатата стойност) в производните на класа класове също са виртуални дори ако запазената дума virtual бъде пропусната. • Виртуалните функции се наследяват като другите компоненти на класа. • Виртуалните функции се извикват чрез указател към или псевдоним на обект от някакъв клас. • Виртуалните функции не могат да бъдат декларирани като приятели на други класове.

  18. Виртуални функции и виртуални класове Множествено наследяване • Производен клас на два или повече базови point color pointcol

  19. Виртуални функции и виртуални класове Множествено наследяване • Производният клас наследява компонентите на всички базови, като типа на наследяването се задава поотделно за всеки базов клас. class point { int x,y; . . . }; class color { int cl; . . . }; class pointcol:public point,public color { . . . }; Деклариране на производен клас на два базови класа

  20. Виртуални функции и виртуални класове Общ вид на конструктор на производен с два базови Множествено наследяване • параметри1 (параметри2+параметри3) са параметрите на pointcol; • параметри2 са параметрите за предаване на point • параметри3 са параметрите за предаване на color • Конструкторите се извикват в реда: 1) конструктор на point; 2) конструктор на color; 3) конструктор на pointcolor. • Деструкторите се извикват в обратен ред. • Ако базов клас се явява също производен, тонаследените компоненти се използват чрез многократно задаване на операцията :: pointcol:pointcol(параметри1):point(параметри2),color(параметри3) { . . . }

  21. Виртуални функции и виртуални класове #include <iostream.h> 1/2 class point { protected: int x, y; public: point(int a, int b) { x = a; y = b; cout <<“Конструктор point.\n”; } ~point() { cout << “Деструктор point.\n”; } void out() { cout << “Координати: “ << x << “ “ << y << “\n”; } }; class color { protected: int cl; public: color(int c=0) { cl = c; cout <<“Конструктор color.\n”; } ~color() { cout << “Деструктор color.\n”; } void out() { cout << “Цвят: “ << cl << “\n”; } }; Множествено наследяване Пример за множествено наследяване

  22. Виртуални функции и виртуални класове Извикването на конструкторите зависи от декларацията на производния клас Множествено наследяване class pointcol : public point, public color 2/2 { public: pointcol(int a, int b, int c) : color(c),point(a,b) { cout <<“Конструктор pointcol.\n”; } ~pointcol() { cout << “Деструктор pointcol.\n”; } void out() { point :: out(); color :: out(); } }; void main() { pointcol p(3,9,2); p.out(); p.point :: out(); p.color :: out(); } Конструктор point. Конструктор color. Конструктор pointcol. Координати: 3 9 Цвят: 2 Координати: 3 9 Цвят: 2 Деструктор pointcol. Деструктор color. Деструктор point.

  23. Виртуални функции и виртуални класове Множествено наследяване classder : publicbase2, base1, base3 {public: der(intx = 0) : base3(x), base1(x), base2(x) {d = 5; } private: intd; intb1, b2, b3; //член данни на base1, base2, base3 }; . . . der object(6); Класът има 2 собствени и 3 наследени компоненти Инициализира 4-те член данни на object с 6

  24. Виртуални функции и виртуални класове Множествено наследяване • Чрез обект на производния клас могат да се викат всички негови public компоненти – собствени и наследени. • Ако в базовите класове са дефинирани компоненти с еднакви имена, необходимо е да се използва пълното име на компонентата. • Ако всички основни класове basei на производния клас der имат член-функция f() и член-данна x с еднакви имена, различаването им в производния клас става чрез пълните им имена: base1::f(), base2::f(), ... base1::x, base2::x, ...

  25. Виртуални функции и виртуални класове Виртуални класове class Base { int a; . . . }; class Drv1 : public Base { . . . }; class Drv2 : public Base { . . . } class Drv3 : public Drv1, public Drv2 { . . . } Drv3 наследява двукратно Base Проблем при член данните

  26. Виртуални функции и виртуални класове Виртуални класове • При йерархията на класове с множествено (многократно) наследяване достъпът до наследените компоненти се извършва с операцията за принадлежност (::). • Член-данните на класа Base ще се появят два пъти във всички обекти на Drv3 (през Drv1 иDrv2). • Член-функциите имат едно копие. Base :: Drv1 :: a или Base :: Drv2 :: a

  27. Виртуални функции и виртуални класове Виртуални класове class Base 1/2 { protected: int i; ………. }; class Drv1:public Base { protected: int j; ……. }; class Drv2:public Base { protected: int k; ……… }; class Drv3:public Drv1, public Drv2 { protected: int sum ……….. }; Множествено наследяване – вариант нееднозначност

  28. Виртуални функции и виртуални класове Виртуални класове Нееднозначност! копие на i от Drv1 или от Drv2 void main() 2/2 { Drv3 ob; ob.i=10; ob.j=20; //коректно - j има едно копие в Drv3 ob.k=30; //коректно - k има едно копие в Drv3 ob.sum=ob.j+ob.k; cout<<ob.sum; //извежда се 50 }

  29. Виртуални функции и виртуални класове Виртуални класове class Base { protected: int i; ………. }; class Drv1:public Base { protected: int j; ……. }; class Drv2:public Base { protected: int k; ……… }; class Drv3:public Drv1, public Drv2 { protected: int sum ……….. }; Множествено наследяване – вариант на нееднозначностпремахната с оператор ::

  30. Виртуални функции и виртуални класове Виртуални класове нееднозначността е премахнатас оператор :: void main() { Drv3 ob; ob.drv1::i=10; ob.j=20; //коректно - j има едно копие в Drv3 ob.k=30; // коректно - k има едно копие в Drv3 ob.sum=ob.j+ob.k+ob.drv1::i; cout<<ob.sum; //извежда се 60 }

  31. Виртуални функции и виртуални класове Виртуални класове class Base { protected: int i; ………. }; class Drv1 : virtual public Base { protected: int j; ……. }; class Drv2:virtual public Base { protected: int k; ……… }; class Drv3:public Drv1, public Drv2 { protected: int sum ……….. }; дублирането е премахнато със създаване само на едно копие в Drv3

  32. Виртуални функции и виртуални класове Виртуални класове • Променя се типът на наследяване на базовия клас от преките му наследници, като се описва, че той се наследява виртуално. Коректно е. В Drv3 има само едно копие void main() { Drv3 ob; ob.i=10; ob.j=20; //коректно - j има едно копие в Drv3 ob.k=30; // коректно - k има едно копие в Drv3 ob.sum=ob.j+ob.k+ob.i; cout<<ob.sum; //извежда се 60 Drv1 my; my.i=80; //virtual на Base не влияе на Drv1 }

  33. Виртуални функции и виртуални класове Виртуални класове Конструктори и деструктори • Класът Base e virtual. Създаването на обект на Drv3 трябва да доведе до еднократно създаване на член-променливите на Base. • Параметрите на конструктора на Base се определят от конструктора на Drv3. • Дефинираните в конструкторите на Drv1 и Drv2 извиквания на конструктора на Base се използват само при създаване на собствените им обекти.

  34. Виртуални функции и виртуални класове Виртуални класове Конструктори и деструктори • Ако има виртуални класове, то техните конструктори се извикват най-напред. • Редът на извикване на останалите зависи от реда на деклариране в Drv3. • Деструкторите се извикват в обратен ред.

  35. Виртуални функции и виртуални класове Виртуални класове Пример за използване на конструктори и деструктори Базов клас - virtual Обект на pegasus ще съдържа еднократно данните на animal

  36. Виртуални функции и виртуални класове Пример за използване на конструктори и деструктори #include <iostream.h> 1/4 enum COLOR {red,green,white,black,brown}; class animal { protected: int age public: animal(int age_n):age(age_n) { cout<<”конструктор animal\n”; } virtual ~animal() { cout<<”деструктор animal\n”; } virtual int get_age() { return age; } virtual void set_age(int age_n) { age=age_n; } }; Дефиниция на базов клас

  37. Виртуални функции и виртуални класове Пример за използване на конструктори и деструктори class horse:virtual public animal 2/4 { protected: int height; COLOR col; public: horse(int age_n,COLOR c,int h): animal(age_n),col(c),height(h) { cout<<”конструктор horse\n”; } ~horse() { cout<<”деструктор horse\n”; } }; class bird:virtual public animal { protected: COLOR col; public: bird(int age_n,COLOR c):animal(age_n),col(c) { cout<<”конструктор bird\n”; } ~bird() { cout<<”деструктор bird\n”; } }; Дефиниция на клас наследник – I ниво Инициализират се данни на базовия класисобствени данни Дефиниция на клас наследник – I ниво

  38. Виртуални функции и виртуални класове Пример за използване на конструктори и деструктори Дефиниция на клас наследник – II ниво class pegasus:public horse,public bird 3/4 { long nbr_believers; public: pegasus(COLOR c,int h,long n,int age_n): animal(age_n*2), horse(age_n,c,h),bird(age_n,c),nbr_beleivers(n) { cout<<”конструктор pegasus\n”; } }; аnimal (virtual) class се инициализира в конструктора на наследника на II ниво

  39. Виртуални функции и виртуални класове Пример за използване на конструктори и деструктори void main() 4/4 { pegasus *p=new pegasus(white,5,100,2); int age=p->get_age(); cout<<”този пегас е на “<<age<<” години\n”; delete p; } конструктор animal конструктор horse конструктор bird конструктор pegasus този пегас е на 4 години деструктор pegasus . . . деструктор animal

  40. Виртуални функции и виртуални класове Абстрактни (контейнерни) класове • Чисти виртуални функции – имат само декларации • Дефинирането на тези функции се извършва в класовете наследници. • Абстрактен клас – клас, който има поне една чиста виртуална функция. • Не се създават обекти на абстрактен клас. • Абстрактните класове служат като базови на други класове. Чрез тях се обединяват в обща структура различни йерархии.

  41. Виртуални функции и виртуални класове Абстрактни (контейнерни) класове • Полиморфизмът позволява създаването на класове с различна логическа структура, които могат да включват обекти от други класове. • Логическата структура на класа се реализира отделно от обектите, които се включват в него. • Връзката между тях се реализира чрез указатели към контейнери, които съхраняват обекти от различни класове. • Логическата структура на контейнерните класове може да е различна – масив, списък и т.н.

  42. Виртуални функции и виртуални класове Абстрактни (контейнерни) класове • Пример: Да се напише програма, която създава хетерогенен едносвързан списък, в който могат да съхраняват обекти от два класа: point(точка) иcomplex (комплексно число).

  43. Виртуални функции и виртуални класове • Пример current NULL begin Обект 1 Обект 1 Обект 1 Обект 2 Обект 3

  44. Виртуални функции и виртуални класове • Пример #include <iostream.h>1/6 #include <stddef.h> class base { public: virtual void out() = 0;//чиста виртуална функция }; struct element { element *next; //указател към следващ елемент void *content;//указател към произволен обект }; class list { element *begin; //указател към началото на списъка element *current;//указател към текущ елемнт public: list() { begin = NULL; current = begin; } ~list();

  45. Виртуални функции и виртуални класове • Пример void new(void *); //добавя нов елемент в списъка 2/6 void first(){ current = begin; } //позициониране върху 1-ви елемент void *next_el() //връща адреса на текущия елемент { void *ad = NULL;//или NULL при последен елемент if(current != NULL)//и позиционира на следващ елемент { ad = current -> content; current = current -> next; } return ad; } void out_list(); //извежда списъка int end()//връща 1 при край на списък { return (current == NULL); } };

  46. Виртуални функции и виртуални класове • Пример list :: ~list() 3/6 { element *next_el; current = begin; while(current != NULL) { next_el = current -> next; delete current; current = next_el; } } void list :: new(void *x) { element *adel = new element; adel -> next = begin; adel -> content = x; begin = adel; } Дефиниция на деструктор Дефиниция на функция за добавяне на нов елемент

  47. Виртуални функции и виртуални класове • Пример void list :: out_list() 4/6 { base *ptr; first(); while( !end() ) { ptr = (base*)next_el(); ptr -> out(); } } class point : public base { int x,y; public: point(int a = 0, int b = 0) { x=a; y=b; } void out() { cout << “точка: “ << x << “ “ << y << “\n”; } }; Дефиниция на фумкция за извеждане на списъка Дефиниция на клас точка

  48. Виртуални функции и виртуални класове • Пример Дефиниция на клас комплексно число class complex : public base5/6 { double r, i; public: complex(double a = 0, double b = 0) { r=a; i=b; } void out() { cout << “комплексно число: “ << r << “+“ << i<< “i\n”; } };

  49. Виртуални функции и виртуални класове • Пример void main() 6/6 { list l; point a(5,6), b(7,8); complex x(1.2,3.4), y(0.2,0.4); l.new(&a); l.new(&x); l.out_list(); l.new(&y); l.new(&b); l.out_list(); } Обект списък с елементи – обекти точки и комплексни числа Добавя в списъка точка и комплексно число Добавя в списъка комплексно число и точка комплексно число: 1.2+3.4i точка: 5 6 точка: 7 8 комплексно число: 0.2+0.4i комплексно число: 1.2+3.4i точка: 5 6

More Related