




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+编程之理解虚函数本文目的了解虚函数的定义、应用场合、内部实现机制以及注意事项。什么是虚函数?缺省情况下,类的成员函数是非虚拟的(nonvirtual)。当一个成员函数为非虚拟的时候,通过一个类对象(指针或引用)而被调用的该成员函数,就是该类对象的静态类型中定义的成员函数。当类的成员函数被virtual关键字修饰时,该函数就是虚函数。当成员函数是虚函数时,通过一个类对象(指针或引用)而被调用的该成员函数,是在该类对象的动态类型中被定义的成员函数。普通函数虚函数class 类名public:函数说明;class 类名public:virtual 函数说明;对于动态类型的理解:虚函数允许派生类取代基类所提供的实现。为什么使用虚函数?C+中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。简单的例子:/基类Aclass Apublic:virtual void describe()cout This is A. endl;/类B派生于基类Aclass B : public Apublic:virtual void describe()cout This is B. describe();delete p;p = new B();p-describe();delete p;return 0;输出结果:什么时候使用虚函数?在实际开发过程中,当我们使用一些类库或框架时,这些类库和框架是事先定义或设计好的,我们不能直接修改类库或框架的代码,这样我们只能派生类库或框架中的类来覆盖一些成员函数以实现我们的功能,但这些成员函数是由类库或框架来调用的,这种情况下,使用虚函数是很好的解决办法。追根究底虚函数的实现机制l 虚函数表 C+规定了虚函数的行为,但将实现方法留给了编译器作者。不需要知道实现方法就可以使用虚函数,但了解虚函数的工作原理有助于更好地理解概念。例子:计算类的大小是多少?class Apublic:void describe()cout This is A. endl;int main(int argc, char* argv)A a;cout 求a对象的大小: sizeof(a) endl;return 0;输出结果:例子:计算类的大小是多少?class Apublic:void describe()cout This is A. endl;/虚函数virtual void func1()cout Call fun1 in Class B. endl;int main(int argc, char* argv)A a;cout 求a对象的大小: sizeof(a) endl;return 0;输出结果:对C+ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。通常,编译器处理虚函数的方法是:给每个对象添加一个隐藏成员。隐藏成员中包含了一个指向函数地址数组的指针。这种数组成为虚函数表(virtual function table, vtbl)。虚函数表中存储了为类对象进行声明的虚函数的地址。例如,基类对象包含一个指针,该指针指向基类中所有虚函数的地址表。派生类对象将包含一个指向独立地址表的指针。如果派生类提供了虚函数的新定义,该虚函数表将保存新函数的地址;如果派生类没有重新定义虚函数,该vtbl将保存函数原始版本的地址。如果派生类定义了新的虚函数,则该函数的地址也将被添加到vtbl中。注意,无论类中包含的虚函数是1个还是多个,都只需要在对象中添加1个地址成员,只是表的大小不同而已。这里我们着重看一下这张虚函数表。C+的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能如果有多层继承或是多重继承的情况下)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。类Class虚函数表虚函数表地址Vfptr(1)Vfptr(2)Vfptr(n)成员变量成员变量l 虚函数的调用调用虚函数时,程序将查看存储在对象中vtbl地址,然后转向对应的函数地址表。如果使用类生命中的第一个函数,则程序将使用数组中第一个函数地址,并执行具有该地址的函数。如果使用类声明中的第二个虚函数,程序将使用地址为数组中第二个元素的函数。/ Project1.cpp : Defines the entry point for the console application./#include stdafx.h#include using namespace std;/基类Aclass Apublic:void describe()cout This is A. endl;/虚函数virtual void func1()cout Call fun1 in Class A. endl;/虚函数virtual void func2()cout Call fun2 in Class A. endl;private:/int a;/类B派生于基类Aclass B : public Apublic:/普通函数void describe()cout This is B. endl;/虚函数virtual void func1()cout Call fun1 in Class B. endl;/虚函数virtual void func2()cout Call fun2 in Class B. endl;/int _tmain(int argc, _TCHAR* argv)int main(int argc, char* argv)B b;A *p = &b;/*获取虚函数表地址*typedef void (*Fun)(void);Fun pFun = NULL;int *vptrAddr = (int *)(&b);int *vtblAddr = (int *)*vptrAddr;cout 虚函数表地址: vptrAddr endl;cout 第一个虚函数地址 vtblAddr endl;cout 第二个虚函数地址 vtblAddr + 1 function();/通过虚拟机制动态调用pBase -Base:function (); /在编译时刻静态调用l 虚析构函数前面讲过,我们可以将一个基类指针指向一个派生类,并且可以方便的调用派生类成员函数,但当我们如果没有将基类的析构函数声明为虚函数,情况会怎么样呢?/基类Aclass Apublic:void describe()cout This is A. endl;A() cout Call class As destroy functiong. endl;/类B派生于基类Aclass B : public Apublic:void describe()cout This is B. endl;B() cout Call class Bs destroy functiong. describe();delete pA;return 0;输出结果:上述结果显示,基类若没有声明虚析构函数,则基类指针指向的对象被销毁时,不会调用派生类的析构函数。这也就意味着,如果在派生类中分配了资源,派生类的资源回收放在派生类的析构函数中,这样的资源就不会被系统所回收,造成内存泄露。下面的例子将基类的析构函数声明为虚析构函数:/基类Aclass Apublic:void describe()cout This is A. endl;virtual A() cout Call class As
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 互联网运营数据分析报告模板指导
- 2025年老年医学老年疾病综合治疗策略模拟考试卷答案及解析
- 2025年肿瘤科治疗方案设计与评估模拟测试卷答案及解析
- 2025年消化内科常见病诊断筛查考试答案及解析
- 2025年康复医学截肢术后康复功能训练考试卷答案及解析
- 初中英语疑问句语法讲解
- 2025年精神科常见疾病症状评估与干预策略考核答案及解析
- 2025-2030纺织服装柔性供应链构建方法研究报告
- 2025-2030番茄种植智慧农业技术应用与精准管理实践分析报告
- 2025-2030浮船升降机行业新兴技术应用与商业模式创新报告
- 2025民航西藏空管中心社会招聘14人(第1期)笔试参考题库附带答案详解(10套)
- 2025年职业病医师资格认证考试
- Unit4《Lesson 3 I am proud of my father》教案-2025-2026学年冀教版(三起)(2024)小学英语四年级上册
- 消防队伍管酒治酒课件
- 医学继续教育管理办法
- 夜间驾驶知识课件
- 动荡变化中的春秋时期
- 2025辅警考试题库(含答案)
- QGDW10212-2019电力系统无功补偿技术导则
- 牛奶面包食品配送服务 投标方案(技术方案)
- 菜鸟驿站运营管理制度
评论
0/150
提交评论