标签:style blog http io ar color os 使用 sp
多态性就是不同对象收到相同消息时,产生不同的动作。用一个名字定义不同的函数,这些函数执行不同但又类似的操作,即用同样的接口访问功能不同的函数,实现“一个接口,多种方法”。
C++支持的多态性分为编译时多态性和运行时多态性。其中编译时多态性主要通过函数重载和操作符重载来实现,而运行时多态通过继承和虚函数来实现。
使用:
1 #include<iostream>
2 using namespace std;
3
4 class my_base
5 {
6 int a,b;
7 public:
8 my_base(int x,int y)
9 {
10 a=x;
11 b=y;
12 }
13
14 void show()
15 {
16
17 cout<<"my_base--------"<<endl;
18 cout<<a<<" "<<b<<endl;
19 }
20
21 };
22
23 class my_class:public my_base
24 {
25
26 int c;
27 public:
28
29 my_class(int x,int y,int z):my_base(x,y)
30 {
31
32 c=z;
33 }
34
35 void show()
36 {
37
38 cout<<"my_class----------"<<endl;
39 cout<<"c="<<c<<endl;
40 }
41 };
42
43 void main()
44 {
45
46 my_base mb(50,50),*ptr;
47 my_class mc(10,20,30);
48 ptr=&mb;
49 ptr->show ();
50 ptr=&mc;
51 ptr->show ();
52
53 }
运行结果如下:
引入派生类后,使用对象指针应该主义的几个问题:1)声明为指向基类对象的指针可以指向它的公有派生对象,但不允许指向它的私有派生的对象。2)不能将一个声明为指向派生类对象的指针指向其基类的对象。3)声明为指向基类对象的指针,当其指向公有派生类对象时,只能用它来直接访问从基类继承来的成员,而不能直接访问公有派生类中定义的成员。
1 对于3)的说明:
2
3 Class A{//...
4 Public:
5 Void print1();
6 };
7
8 Class B: Public A{//....
9
10 Public:
11 Void print2();
12 };
13
14 Void main()
15 {
16
17 A op1,*ptr;//定义基类A的对象op1和基类指针ptr
18 B op2;
19 Ptr=&op1;
20 Ptr->print1();
21 Ptr=&op2;
22 Ptr->print1();
23 Ptr->print2(); //错误,不能访问派生类中定义的成员函数print2()
24 }
如果需要访问其公有派生类中的特定成员,可以将基类指针用显式类型转换为派生类指针。错误语句可以改写为:((B*)ptr)->print2(); 外层括号表示对ptr强制转换,而不是返回类型。
2.1.2虚函数的定义和使用
使用虚函数,实现动态调用功能。多态性实现了在基类定义派生类所拥有的通用接口,而在派生类定义具体的实现方法。虚函数的定义在基类中进行,在需要定义为虚函数的成员函数的声明中冠以virtual关键字,从而提供一种接口界面。
定义方法:
Virtual 函数类型 函数名(形参列表)
{函数体}
1 #include<iostream>
2
3 using namespace std;
4
5 class parent
6
7 {
8
9 protected:
10
11 char version;
12
13 public:
14
15 parent()
16
17 {
18
19 version=‘A‘;
20
21 }
22
23 virtual void print()
24
25 {
26
27 cout<<endl<<"The parent.version "<< version;
28
29 }
30
31 };
32
33 class derived1:public parent
34
35 {
36
37 private :
38
39 int info;
40
41 public:
42
43 derived1(int number)
44
45 {
46
47 info=number;
48
49 version=‘1‘;
50
51 }
52
53 void print()
54
55 {
56
57 cout<<endl<<"The derived1 info:"<<info<<" version "<<version;
58
59 }
60
61 };
62
63 class derived2:public parent
64
65 {
66
67 private :
68
69 int info;
70
71 public:
72
73 derived2(int number)
74
75 {
76
77 info=number;
78
79 }
80
81 void print()
82
83 {
84
85 cout<<endl<<"The derived2 info:"<<info<<" version "<<version<<endl;
86
87 }
88
89 };
90
91 void main()
92
93 {
94
95 parent ob,*op;
96
97 op=&ob;
98
99 op->print ();
100
101 derived1 d1(3);
102
103 derived2 d2(15);
104
105 op=&d1;
106
107 op->print ();
108
109 op=&d2;
110
111 op->print ();
112
113 }
关于虚函数定义的几点说明:
1)在基类中利用关键字virtual可以将public和protected部分的成员函数声明为虚函数;
2)在派生类中对虚函数进行重新定义时,可以写virtual也不可以不写,当不写时遵循三个规则来判断(名称、参数个数和类型、返回类型);
3)虚函数重新定义时其函数原型必须与基类中全完相同;
4)只有通过基类指针访问虚函数时才能获得运行时的多态性,使用对象名和点运算符的调用方式是在编译时的静态连编;
5)一个虚函数无论被公有继承多少次,仍然保持其虚函数的特性;
6)虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数。但虚函数可以在另一个类中被声明为友元函数;
7)构造函数不能是虚函数,但是析构函数可以。
虚函数与重载函数的区别:当普通函数重载时,其函数的参数或参数类型必须有所不同,函数的返回类型也可以不同。但是当重载一个虚函数时要求其原型完全相同。如果仅仅返回类型不同,其余相同,系统会给出出错信息;如果仅仅函数名相同,参数的个数类型或顺序不同,系统将它作为普通的函数重载,从而丢失虚函数的特性。
·多重继承与虚函数
1 #include <iostream.h>
2
3 Class base1{
4
5 Public:
6
7 Virtual void fun() //定义为虚函数
8
9 {cout<<”--base1--”<<endl;}
10
11 };
12
13 Class base2{
14
15 Public:
16
17 void fun()//定义为普通成员函数
18
19 {cout<<”--base2--”<<endl;}
20
21 };
22
23 Class derived:public base1,public base2{
24
25 Public:
26
27 Void fun()
28
29 {cout<<”--derived--”<<endl;}
30
31 };
32
33
34
35 Void main()
36
37 {
38
39 Base1 *ptr1;
40
41 Base2 *ptr2;
42
43 Derived obj3;
44
45 Ptr1=&obj3;
46
47 Ptr1->fun();//此处调用派生类derived的fun()
48
49 Ptr2=&obj3;
50
51 Ptr2->fun();//此处调用的是基类base2的fun()
52
53 }
纯虚函数是一个在基类中说明的虚函数,它在该基类中没有定义,但要求在它的派生类中定义自己的版本,或重新说明为虚函数。
纯虚函数的一般形式:
Virtual 函数类型 函数名(参数表)=0;
如果一个类至少有一个纯虚函数,那么就称该类为抽象类。关于抽象类使用的一些注意:1)抽象类只能用作其他类的基类,不能建立抽象类对象;2)抽象类不能用作参数类型、函数类型或显示转换的类型,但可以声明指向抽象类的指针或引用,该指针可以指向它的派生类。3)如果在抽象类的派生类中没有重新说明纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。4)在抽象类中也可以定义普通成员函数或虚函数,虽然不能为抽象类声明对象,但仍然可以通过派生类对象来调用这些不是纯虚函数的函数。5)不允许从具体类派生出抽象类。
程序示例:在这个程序中,建立两种类型的表,队列和栈。虽然两个表完全不同,但他们可以用同一个接口访问。
1 #include<iostream.h>
2
3 #include<stdlib.h>
4
5 #include<ctype.h>
6
7 Class list
8
9 {
10
11 Public:
12
13 List *head;
14
15 List *tail;
16
17 List *next;
18
19 Int num;
20
21 List()
22
23 {
24
25 Head=tail=next=NULL;
26
27 }
28
29 Virtual void store(int i)=0;
30
31 Virtual void retrieve()=0;
32
33 };
34
35 Class queue:public list
36
37 {
38
39 Public:
40
41 Void store(int i);
42
43 Int retrieve();
44
45 };
46
47
48
49 Void queue::store(int i)
50
51 {
52
53 List *item;
54
55 Item=new queue;
56
57 If(!item)
58
59 {
60
61 Cout<<”Allocation error”<<endl;
62
63 Exit(1);
64
65 }
66
67 Item->num-i;
68
69 If(tail)tail->next=item;
70
71 Tail=item;
72
73 Item->next=NULL;
74
75 If(!head)
76
77 Head=tail;
78
79 }
80
81
82
83 Int queue::retrieve()
84
85 {
86
87 Int i;
88
89 List *p;
90
91 If(!head)
92
93 {
94
95 Cout<<”list empty”<<endl;
96
97 Return 0;
98
99 }
100
101 I=head->num;
102
103 P=head;
104
105 Head=head->next;
106
107 Delete p;
108
109 Return i;
110
111 }
112
113
114
115 Class stack:public list
116
117 {
118
119 Public:
120
121 Void store(int i);
122
123 Int retrieve();
124
125 };
126
127 Void stack::store(int i)
128
129 {
130
131 List *item;
132
133 Item=new stack;
134
135 If(!item)
136
137 {
138
139 Cout<<”Allocation error”<<endl;
140
141 Exit(1);
142
143 }
144
145 Item->num=i;
146
147 If(head)item->next=head;
148
149 Head=item;
150
151 If(!tail)
152
153 tail=head;
154
155 }
156
157
158
159 Int stack::retrieve()
160
161 {
162
163 Int i;
164
165 List *p;
166
167 If(!head)
168
169 {
170
171 Cout<<”list empty”<<endl;
172
173 Return 0;
174
175 }
176
177 I=head->num;
178
179 P=head;
180
181 Head=head->next;
182
183 Delete p;
184
185 Return i;
186
187 }
188
189
190
191 Main()
192
193 {
194
195 List *p;
196
197 Queue q_ob;
198
199 P=&q_ob;
200
201 P->store(1);
202
203 P->store(2);
204
205 P->store(3);
206
207 Cout<<”queue:”;
208
209 Cout<<p->retrieve();
210
211 Cout<<p->retrieve();
212
213 Cout<<p->retrieve();
214
215 Cout<<endl;
216
217 Stack s_ob;
218
219 P=&s_ob;
220
221 P->store(1);
222
223 P->store(2);
224
225 P->store(3);
226
227 Cout<<”stack:”;
228
229 Cout<<p->retrieve();
230
231 Cout<<p->retrieve();
232
233 Cout<<p->retrieve();
234
235 Cout<<endl;
236
237 Return 0;
238
239 }
运行结果:
Queue:123
Stack:321
标签:style blog http io ar color os 使用 sp
原文地址:http://www.cnblogs.com/wendingding/p/4165989.html