Полиморфизмът е свойство на член-функциите и се реализира с
виртуални функции.
Той се състои в осигуряване възможността генерирания код да се държи по различен начин в зависимост от условия, определяни по време на изпълнението на програмата.
Идеята на тези функции се основава на вида на свързването им (
статично или
ранно и съответно
динамично или
късно)
1.
Статичното свързване на типа на обекта с извикваната член-функция става по време на компилацията и не се променя при изпълнение на програмата. Свързващият редактор замества имената на извикваните функции с конкретните им адреси.
Пример илюстриращ
статично свързване
CODE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| class point
{ protected:
int x,y;
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”; }
};
void main()
{ point p(3,5),*adp=&p;
pointcol pc(8,6,2),*adpc=&pc; [color=blue]//Резултати от изпълнение[/color]
adp->out(); [color=blue]//извиква се out на point[/color] [color=red]точка:3 5[/color]
adpc->out();[color=blue]//извиква се out на pointcol[/color] [color=red]оцветена точка:8 6 2[/color]
adp=adpc; [color=blue]//по време на изпълнението[/color]
adp->out(); [color=blue]//но adp е point по време[/color] точка:3 5
adpc->out();[color=blue]//на компилация[/color] [color=red]оцветена точка:8 6 2[/color]
} |
2.
Динамичното свързване на типа на обекта с извикваната член-функция е по време на изпълнение на програмата. При извикването на функция се задава само името, но не и конкретния адрес на прехода. Или по време на изпълнение се дава възможността за промяна на връзките между имена и адреси. Късното свързване се определя чрез думата
virtual.
Пример илюстриращ
динамично свързване
CODE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| class point
{ protected:
int x,y;
point(int a=0,int b=0) { x=a; y=b; }
virtual 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() [color=blue]//също е virtual(с или без служебна дума)[/color]
{ cout<<”оцветена точка:”<<x<<” “<<y<<”с цвят:”<<color<,”n”;}
};
void main()
{ point p(3,5),*adp=&p;
pointcol pc(8,6,2),*adpc=&pc; [color=blue]//Резултати от изпълнение[/color]
adp->out(); [color=blue]//извиква се out на point[/color] [color=red]точка:3 5[/color]
adpc->out();[color=blue]//извиква се out на pointcol[/color] [color=red]оцветена точка:8 6 2[/color]
adp=adpc; [color=blue]//по време на изпълнението[/color]
adp->out(); [color=blue]//adp е pointcol по време[/color] [color=red]оцветена точка:8 6 2[/color]
adpc->out();[color=blue]//на изпълнение[/color] [color=red]оцветена точка:8 6 2[/color]
} |
Или
указател на
базовия клас се използва за
извикване на
член-функции на производния клас вместо едноименните (предефинирани) функции на базовия (последните са
virtual).
Пример за извикване на член-функция на базата на динамичния тип на викащия обект
CODE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| class animal
{ protected:
int age;
public:
animal(): age(1) { }
virtual void [b]speak[/b]() { cout<<”Animal speaks.n”; }
};
class dog:public animal
{ public:
void [b]speak[/b]() { cout<<”Baow.n”; }
};
class cat:public animal
{ public:
void [b]speak[/b]() { cout<<”Meow.n”; }
};
class pig:public animal
{ public:
void [b]speak[/b]() { cout<<”Grouch.n”; }
};
void main()
{ animal *a[4],*ptr;[color=blue]//масив от указатели към базов клас и указател[/color]
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; [color=blue]//ptr се свързва с обектите[/color]
case 2: ptr=new cat; break; [color=blue]//по време на изпълнение[/color]
case 3: ptr=new pig; break;
default:ptr=new animal;
}
a[i]=ptr;
}
for(i=0;i<4;i++) a[i]->speak();
} |
Резултати от изпълнение
(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.
speak е
virtual функция и ще се извиква в зависимост от това къде сочи указателя в момента на изпълнение.
- При наличие на виртуална функция – деструкторът трябва да е виртуален.
- Конструкторът не може да бъде виртуален.
- Ако е предефинирана виртуална функция, но с друг брой на параметрите, то това е друга функция и няма динамично свързване с нея.
- Виртуалните функции могат да са приятелски на други класове.