C++多态实现机制

转自:https://www.cnblogs.com/InitialD/p/7462587.html

多态是OOP中一个十分重要的特性,至于如何使用可以参考这篇C++与JAVA多态相同与不同,相信对于学习C++和java的人都有帮助。

多态实现的关键技术是动态绑定。

动态绑定:程序在运行期间寻找函数地址

静态绑定:代码在编译时已经确定了函数地址

 

多态的实现表象是指针+虚函数,本质是虚表+虚指针。

这里有一篇博客写的很全面,可以参考一下c++多态实现的机制

 

1.虚表

声明了虚函数的类会隐式创建一个虚指针指向虚表,而虚表保存了虚函数的地址(虚表中只有虚函数,非虚函数在另一个表中),当我们调用虚函数时,实际上是通过虚指针去查找虚表中对应虚函数的地址

2.虚指针

虚指针指向类的虚表,属于类的成员变量,可以继承,当子类继承父类的虚指针时,子类的虚指针指向子类的虚表。虚表也可以继承,也可以理解为继承了虚函数,然后创建了自己的虚表,所以如果没有重定义父类虚函数,那么子类虚表和父类虚表完全相同;重定义的虚函数在子类虚表中的地址会改变。

3.虚指针的初始化

虚指针在构造函数中进行初始化,指向类的虚表。如果类B继承了类A,那么我们知道生成B的实例对象时,会先调用A的构造函数,此时虚指针指向A的虚表,然后调用B的构造函数,此时虚指针指向B的虚表,所以当B的实例构造完成后,虚指针指向B的虚表。

4.多态

用下面的例子讲解,当我们声明一个父类A的指针p指向子类B的对象时,在编译阶段是不分配内存的(不构造对象的),如果想了解编译过程做了什么,可以参考一下这篇C程序编译过程浅析。也就是说编译器并不知道指针p指向的是B类的对象,只知道这是一个A类的指针,那么在编译p->func()时,会直接查找A中func的地址并替换(可以简单理解为这样),也就是静态绑定,那么在运行时自然调用的就是A的func了

复制代码
 1 class A
 2 {
 3 public:
 4     A(){};
 5     void func()
 6     {
 7         cout << "A func called!";
 8     }
 9 };
10 
11 class B:public A
12 {
13 public:
14     B(){};
15     void func()
16     {
17         cout << "B func called!";
18     }
19 
20 };
21 
22 int main()
23 {
24     A*p = new B();
25     p->func();
26     return 0;
27 }
复制代码

 

但是如果将func声明为虚函数,如下,那么在编译时编译器一看func是虚函数,会直接跳过,那么在运行时,B的对象已经被构造出来了,那么p所指向的B对象的虚指针已经指向了B的虚表,此时调用p->func()时,操作系统会在p的虚表中去寻找func这个函数,也就是动态绑定,然后调用,这时候调用的自然就是B的func了,可以说虚指针和虚表就是为了多态而生的。

复制代码
 1 class A
 2 {
 3 public:
 4     A(){};
 5     virtual  void func()
 6     {
 7         cout << "A func called!";
 8     }
 9 };
10 
11 class B:public A
12 {
13 public:
14     B(){};
15     void func()
16     {
17         cout << "B func called!";
18     }
19 
20 };
21 
22 int main()
23 {
24     A*p = new B();
25     p->func();
26     return 0;
27 }
复制代码

 

看到这里,大家再去看我写的C++与JAVA多态相同与不同,也就明白为什么我说重写和重定义不同了。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值