【c++基础】虚函数的使用以及和成员函数的区别
2016-11-01 14:11
543 查看
前言
一直以来都知道虚函数的经典用法,但是除了本科时刚学c++的时候了解过,后来因为做不同的项目在不同的语言之间跳转(自觉都是浅尝辄止),这些基本的东西都忘记了,现在重拾并记录,权当巩固基础了。经典用法
#include<iostream> using namespace std; //几何体类 class Geometry{ public: virtual void draw(){ cout<<"Geometry Drawing"<<endl; } }; //矩形类 class Rect:public Geometry{ public: virtual void draw(){ cout<<"Rect Drawing"<<endl; } }; //圆类 class Circle:public Geometry{ public: virtual void draw(){ cout<<"Circle Drawing"<<endl; } }; void DrawSomething(Geometry *pG){ pG->draw(); } int main(){ Geometry *geometrys[3]; //1.init geometrys[0]=new Rect(); geometrys[1]=new Geometry(); geometrys[2]=new Circle(); //2.draw all for(int i=0;i<3;i++){ DrawSomething(geometrys[i]); } return 0; }
运行结果:
Rect Drawing
Geometry Drawing
Circle Drawing
用虚函数就可以实现
DrawSomething函数这样接口简单的函数,而不用写
DrawRect、
DrawCircle这样的函数组。
另外这个例子不好的地方是,几何体实际上可以作为一个抽象的概念,应该限制它实例化、此时可以把其中的
draw函数设置为纯虚函数,
virtual void draw()=0;.如此几何体类为一个抽象类,禁止实例化。
原理
首先来看一下c++对象模型图(来自《Inside The C++ Object Model》)图中可以看到只有非静态成员变量和虚表指针是存在对象内的。静态成员函数、成员函数、静态变量是独立存储的(可以认为所有的类对象都共有一份)。虚表指针指向的虚表中存储了所有的虚函数。回到代码中,当执行这句话的时候
pG->draw();时,编译器检测到是需要执行虚函数,就会通过该对象实例的vptr指针找到虚函数的地址,进而调用。所以即使子类的指针被转化为父类指针调用,当我们需要使用虚函数时,依然是调用子类的虚函数(转化的时候,vptr的没有变)。
现在再来看反面,假设我们去掉了上面代码所有的virtual 关键字。运行结果会是如何?结果是:
Geometry Drawing
Geometry Drawing
Geometry Drawing
从对象模型图中可以看出一些差别。该变量是什么类型,就会调用该类型的成员函数(我们的例中,都为Geometry *类型),没有一个vptr去做区分。有点类似于全局函数,如果对象或对象指针调用成员函数(非虚),实际上就是调用这个独立于类实例的函数指针。
总的来说不像虚函数和对象实例紧密相连(通过虚表指针),普通成员函数和类实例是分离的(见模型图)。但是由此产生的问题是,那成员函数如何去使用成员变量呢,实际上编译器隐式的给成员函数加上一个参数,使得调用时可以把this指针传进去,通过this指针就可以调用成员变量了。
补充
关于虚函数的实现原理,参考这篇博客 http://www.cnblogs.com/malecrab/p/5572730.html相关文章推荐
- C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点
- C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点
- C++ 成员函数后面加const,没有const,以及使用的区别
- C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点
- C++关于类成员函数在参数列表后加const的作用,以及使用条件
- C++指向类成员函数的以及虚函数的函数指针
- C++成员函数实现在类定义中与在类定义外的区别(Windows下直接使用g++)
- c++调用类内部使用成员变量和inline函数的区别
- C++中函数覆盖和使用虚函数有什么区别
- 成员函数后面加const,没有const,以及使用的区别
- 成员函数后面加const,没有const,以及使用的区别
- 成员函数后面加const,没有const,以及使用的区别
- C++基础——使用字符串作为函数模板的实参
- C++ 静态成员函数使用不需要声明
- 【C++基础02】类中不写成员函数易犯错误模型
- C/C++:函数的编译方式与调用约定以及extern “C”的使用
- C++中静态成员函数和非静态成员函数的区别
- 详解C++中的函数调用和下标以及成员访问运算符的重载
- 【C++基础】const成员函数
- C++的类成员函数的使用体会