博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ 继承&多态
阅读量:4220 次
发布时间:2019-05-26

本文共 2936 字,大约阅读时间需要 9 分钟。

继承&多态

· 访问限定符

*继承访问控制的作用是将继承下来的成员在派生类域内的属性改变而和原本基类的成员访问控制符关。

 所有的基类private成员在派生类里是不可见,但它确确实实被继承下来了。

 基类的protected成员只对继承它的派生类可见,在类外不可使用

· 派生类列表

  在定义派生类的时候我们必须写出派生类列表,但在声明处不可写。

1.虚函数的使用(多态的实现)

1
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
37
38
39
40
41
42
43
#include<iostream>
using 
namespace 
std;
class 
Base
{
private
:
     
int 
_base ;
public
:
     
Base()
            
:_base (0)
     
{}
     
virtual 
void 
show()
     
{
            
cout << 
"Base::show()" 
<< endl ;
     
}
     
//....
};
class 
D :
public 
Base
{
public
:
     
D()
            
:_d (1)
     
{}
     
void 
show()
     
{
            
cout << 
"D::show()" 
<< endl ;
     
}
 
private
:
     
int 
_d ;
};
void 
Print (Base *pb)
{
     
pb-> show();
}
int 
main ()
{
     
Base b;
     
D d;
     
Print(& b);
     
Print(& d);
     
getchar
();
     
return 
0;
}

*通过传参的不同使得show函数的输出结果不同,实现的原理是:虚函数表(动态绑定)

*动态绑定:函数的运行版本由实参决定,在函数运行时才进行选择,又称运行时绑定

*规则:基类通常都需要定义一个虚析构函数,无论是否在后面用到

*成员函数如果没有被声明为虚函数并且不是静态函数,那它的解析过程发生在编译阶段而不是运行阶段

*每个类控制自己的成员初始化,不要使用派生类直接初始化基类成员

*派生类必须对它内部重新定义的虚函数进行声明

*任何除了构造函数以外的非静态函数都可以是虚函数

2.虚函数表

 a.单继承

  如上例中代码示,单继承时Base的对象模型如下

 D的对象模型如下

 b.多继承 

1
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include<iostream>
using 
namespace 
std;
typedef 
void 
(*PTR)();
class 
Base
{
private
:
     
int 
_base ;
public
:
     
Base()
            
:_base (0)
     
{}
     
virtual 
void 
show()
     
{
            
cout << 
"Base::show()" 
<< endl ;
     
}
     
//...
};
class 
Base2
{
private
:
     
int 
_base2 ;
public
:
     
Base2()
            
:_base2 (2)
     
{}
     
virtual 
void 
show()
     
{
            
cout << 
"Base2::show()" 
<< endl ;
     
}
     
virtual 
void 
fun2()
     
{
            
cout << 
"Base2::fun2()" 
<< endl ;
     
}
     
//...
};
class 
D :
public 
Base,
public 
Base2
{
public
:
     
D()
            
:_d (1)
     
{}
     
void 
show()
     
{
            
cout << 
"D::show()" 
<< endl ;
     
}
     
void 
fun2()
     
{
            
cout << 
"D::fun2()" 
<< endl ;
     
}
     
virtual 
void 
fun3()
     
{
            
cout << 
"D::fun3()" 
<< endl ;
     
}
     
virtual 
void 
fun4()
     
{
            
cout << 
"D::fun4()" 
<< endl ;
     
}
private
:
     
int 
_d ;
};
void 
PrintVT (
int 
p )
     
//实参是每个类存储虚函数指针的地址,解引用之后代表该类的虚函数指针
{
     
PTR ptr = NULL;
     
//现在让pi能访问类的虚函数指针
     
int 
*pi = (
int 
*)p;
     
int 
i = 0;
     
while 
(pi [i ])
     
{
            
ptr = (PTR)pi[i];
            
ptr();
            
i++;
     
}
}
int 
main ()
{
     
//Base b;
     
//Base2 b2;
     
D d;
     
//PrintVT(*(int *)&b);
     
//cout << "--------------------" << endl;
     
//PrintVT(*(int *)&b2);
     
//cout << "--------------------" << endl;
     
PrintVT(*( 
int 
*)&d );
     
cout << 
"--------------------" 
<< endl ;
     
getchar
();
     
return 
0;
 
}

 如上述代码,我们发现多继承的虚函数表和单继承由很大的不同之处

 在此不再赘述两个基类的虚表,我们来看派生类的对象模型

 spacer.gif

*我们发现在派生类中有两个虚函数表,并且派生类自己的虚函数被存入了第一个虚函数表

上述代码运行的结果是

tips:

   *在一个对象中继承自基类的部分和派生类的自定义部分不一定是连续存储的

   *如果在基类里定义了一个静态成员那么这个成员是唯一定义的,只存在一个实例

   *含有关键字final的类不可以作为基类被继承

   *动态绑定基于给用基类的指针或者引用绑定对象。除了内置指针外智能指针也是可以做到这样的     类     型转换的

          

C++的多态性:我们把具有继承关系的多个类型称为多态类型,因为我们可以使用这些类型的多种形式而无须在意他们的差异


覆盖:派生类重新定义了基类的虚函数并且他们的函数名,参数列表和返回值都必须相同但是协变的返              回值必须不同。

隐藏:派生类重新中定义了基类中同名的函数(非虚函数和静态函数)此时基类中的同名函数被隐藏

重载:在同一个作用域内我们定义了几个同名函数他们通过参数列表来区分彼此称为重载


*我们可以在支持C++11的编译器中给覆盖加上override关键字,那么我们在编写该函数时编译器会检查   它形式的正确性,保证我们的调试变得更加简单

http://blog.51cto.com/zimomo/1752936

转载地址:http://utemi.baihongyu.com/

你可能感兴趣的文章
CUDA 学习(五)、线程块
查看>>
CUDA 学习(八)、线程块调度
查看>>
CUDA 学习(九)、CUDA 内存
查看>>
CUDA 学习(十一)、共享内存
查看>>
游戏感:虚拟感觉的游戏设计师指南——第十四章 生化尖兵
查看>>
游戏感:虚拟感觉的游戏设计师指南——第十五章 超级马里奥64
查看>>
游戏感:虚拟感觉的游戏设计师指南——第十七章 游戏感的原理
查看>>
游戏感:虚拟感觉的游戏设计师指南——第十八章 我想做的游戏
查看>>
游戏设计的艺术:一本透镜的书——第十章 某些元素是游戏机制
查看>>
游戏设计的艺术:一本透镜的书——第十一章 游戏机制必须平衡
查看>>
游戏设计的艺术:一本透镜的书——第十二章 游戏机制支撑谜题
查看>>
游戏设计的艺术:一本透镜的书——第十三章 玩家通过界面玩游戏
查看>>
编写苹果游戏中心应用程序(翻译 1.3 为iOS应用程序设置游戏中心)
查看>>
编写苹果游戏中心应用程序(翻译 1.4 添加游戏工具包框架)
查看>>
编写苹果游戏中心应用程序(翻译 1.5 在游戏中心验证本地玩家)
查看>>
编写苹果游戏中心应用程序(翻译 1.6 获取本地玩家的信息)
查看>>
编写苹果游戏中心应用程序(翻译 1.7 在游戏中心添加朋友)
查看>>
编写苹果游戏中心应用程序(翻译 1.8 获取本地玩家的好友信息)
查看>>
WebGL自学教程《OpenGL ES 2.0编程指南》翻译——勘误表
查看>>
WebGL自学教程——WebGL示例:12. 要有光
查看>>