C++多态,虚函数作用及底层实现原理
来源:互联网 发布:plc编程功能块 编辑:程序博客网 时间:2024/06/05 13:33
简述C++虚函数作用及底层实现原理
1.foreword
C++是面向对象程序设计,其包括3项特点:
(1)数据抽象:接口和实现分离
(2)继承:父类和子类
(3)多态:动态绑定
本文讨论多态。
当父类希望子类重新定义某些函数时,用virtual关键字声明为虚函数。
当我们使用一个基类类型的引用或者指针,调用一个虚函数时就引发动态绑定/多态的发生。函数运行版本由传入的实参类型决定。可以用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。
父类指针好像有“多种类型”。这是一种泛型技术,试图用不变的代码实现可变的算法,比如模板技术,虚函数技术等。
引用或者指针的静态类型与动态类型不同这一事实,是C++支持多态的核心。
上述这句话选自《C++ Primer》,颇有玄门正宗之感。复杂的技术根植于底层的原理,所以搞清原理方可深入浅出。
当我们使用基类的引用、指针去调用基类中定义的一个虚函数时,并不知道该函数真正作用的对象是什么类型,可能是一个基类对象,也可能是一个派生类对象,这一切直到运行时才可知道。所以多态又称运行时绑定/动态绑定。
对于非虚函数的调用在编译时即可确定,哪个对象,哪个方法,地址是确定的。
2.虚函数底层实现原理
当你记住上面的概念时,它仅是概念。但当真正了解底层原理后,发现其中妙不可言。
如果让你来实现虚函数的功能?你会怎么实现?
复杂的代码?高深的原理?其实C++中实现的非常接地气。
虚函数是通过虚函数表和虚函数指针来实现的。
该表一般位于某类型的对象实例在内存中的最开始的位置。
单类继承
class Base {public: virtual void f() { cout << "Base::f()" << endl; } virtual void g() { cout << "Base::g()" << endl; } virtual void h() { cout << "Base::h()" << endl; }};
父类对象其在内存中布局示意如下:
虚函数表的尾部为虚函数表的结束结点。
再定义一个子类,此时并不覆盖父类的虚函数:
class Derived :public Base {public: virtual void f1() { cout << "Derived::f1()" << endl; } virtual void g1() { cout << "Derived::g1()" << endl; } virtual void h1() { cout << "Derived::g1()" << endl; }};
此时可以得知:
(1)虚函数按照声明顺序放在表中;
(2)父类的虚函数,排在子类虚函数之前。
当我们把子类中的函数覆盖时:
class Derived :public Base {public: // f() override void f() { cout << "Derived::f1()" << endl; } virtual void g1() { cout << "Derived::g1()" << endl; } virtual void h1() { cout << "Derived::g1()" << endl; }};
此时可以得知:
(1)子类覆盖的虚函数,放在原来父类该虚函数的位置;所以当父类指针指向该子类对象时,调用方法就会调用子类重载的方法;
(2)没有被覆盖的虚函数依旧。
多类继承
当发生多类继承时:
虚函数表内存排列示意如下:
此时可以得知:
(1)每个继承的父类,都有自己的虚函数表;
(2)子类虚函数,放在第一个声明顺序的父类的表中。
当子类虚函数重写时,此时类的继承为:
子类将f( )函数重写,则内存中的排列为:
此时我们可以得知:
(1)三个父类虚函数表中的f( )函数被替换为子类函数指针。因此当我们用任一静态类型的父类指针来指向子类时,调用f( )时就调用的子类的f( )。
参考资料:
[1] http://www.cnblogs.com/webary/p/4731457.html
- C++多态,虚函数作用及底层实现原理
- 简述C++虚函数作用及底层实现原理
- C++中虚继承的作用及底层实现原理
- C++虚函数的底层实现原理
- C++虚函数的底层实现原理
- 虚函数的作用及其底层实现机制
- 虚函数的作用及其底层实现机制
- C语言getbits函数原理及实现
- HashMap和HashSet原理及底层实现
- HashMap底层实现原理及面试问题
- 面试常见题之虚函数及底层的实现
- Redis实现原理及作用
- 虚函数底层实现机制
- SDWebImage底层实现原理及内部实现过程
- SDWebImage底层实现原理及内部实现过程
- SDWebImage底层实现原理及内部实现过程
- extern "C"底层原理
- Struts2底层实现原理
- Java Swing:进度条字体颜色修改
- MySQL+DBUtils+C3P0+ Servlet+HTML完成Web端登陆验证案例实现
- 如何阅读caffe源码
- Python Algorithms Learning Notes(1)--Asymptotic Notations
- linux下pip使用可能遇到的问题
- C++多态,虚函数作用及底层实现原理
- Codeforces Round #426 (Div. 2) C:The Meaningless Game(思维)
- UVa12186 Another Crisis
- verilog中defparam的用法
- 欢迎使用CSDN-markdown编辑器
- ios-对图片进行裁剪得到一个新图片和保存到相册
- xynuoj (贪心) 积木大赛 酒馆浪人的博客
- ccnf
- 用栈模拟汉诺塔问题