参考:http://www.weixueyuan.net/view/6372.html

总结:

  在C++中通过虚成员函数表vtable实现多态,虚函数表中存储的是类中虚函数的入口地址。

  使用多态会降低程序运行效率,使用多态的程序会使用更多的存储空间,存储虚函数表等内容,而且在调用函数时需要去虚函数表中查询函数入口地址,这会增加程序运行时间。

  在设计程序时,程序设计人员可以选择性的使用多态,对于有需要的函数使用多态,对于其它的函数则不要采用多态。

  通常情况下,如果一个类需要作为基类,并且期望在派生类中修改某成员函数的功能,并且在使用类对象的时候会采用指针或引用的形式访问该函数,则将该函数声明为虚函数。

通过前两节的介绍,想必对多态有一定的了解了。这一节将介绍多态是如何实现的,关于如何实现多态,对于程序设计人员来说即使不知道也是完全没有关系的,但是对于加深对多态的理解具有重要意义,故而在此节中稍微阐述一下多态的实现机制。

在C++中通过虚成员函数表vtable实现多态,虚函数表中存储的是类中虚函数的入口地址。在普通的类中是没有虚函数表的,只有在具有虚函数的类中(无论是自身添加的虚函数还是继承过来的虚函数)才会具有虚函数表,通常虚成员函数表的首地址将会被存入对象的最前面(在32位的操作系统中,存储地址是用4个字节,因此这个首地址就会占用对象的前四个字节的空间)。

例1:

#include<iostream>
using namespace std; class base
{
public:
virtual void v1(){ }
virtual void v2(){ }
}; class derived: public base
{
public:
virtual void v1(){ }
virtual void v2(){ }
}; int main()
{
base b;
derived d;
base *p;
p = &b;
p->v1();
p->v2();
p = &d;
p->v1();
p->v2();
return ;
}

我们将两个类定义成例1所示形式,两个类中各有两个虚函数v1和v2,我们将其函数入口地址找到列于下表中:

虚成员函数 函数入口地址 虚成员函数 函数入口地址
base::v1 00D15834 derived::v1 00D15844
base::v2 00D15838 derived::v2 00D15848

虚函数表里面存储的就是虚函数的入口地址。我们再来看主函数,在主函数中先定义了base类对象b,因为b类中有虚函数,因此存在虚函数表,而虚函数表的首地址就存储在对象所在存储空间的最前,具体情况可以见下图。当然声明derived对象d之后,情况也跟下图中一样,同样在对象存储空间中包含虚成员函数表地址。

之后定义了一个基类类型的指针p,当我们通过基类指针p调用虚函数v1或v2时,系统会先去p所指向的对象的前四个字节中寻找到虚函数表地址,之后在内存中找到该虚函数表,然后在表中找到对应函数的入口地址,之后直接访问这个函数了。当p指针指向的是基类对象时,基类的虚函数表将会被访问,基类中虚函数将会被调用。当p指针指向的是派生类对象,则访问的是派生类的虚函数表,派生类的虚函数表中存的是派生类中的虚函数入口地址,因此调用的是派生类中的虚函数。

使用多态会降低程序运行效率,使用多态的程序会使用更多的存储空间,存储虚函数表等内容,而且在调用函数时需要去虚函数表中查询函数入口地址,这会增加程序运行时间。在设计程序时,程序设计人员可以选择性的使用多态,对于有需要的函数使用多态,对于其它的函数则不要采用多态。通常情况下,如果一个类需要作为基类,并且期望在派生类中修改某成员函数的功能,并且在使用类对象的时候会采用指针或引用的形式访问该函数,则将该函数声明为虚函数

4.3 C++虚成员函数表vtable的更多相关文章

  1. C++虚成员函数表vtable

    介绍一下多态是如何实现的,关于如何实现多态,对于程序设计人员来说即使不知道也是完全没有关系的,但是对于加深对多态的理解具有重要意义,故而在此节中稍微阐述一下多态的实现机制. 在C++中通过虚成员函数表 ...

  2. 关于C++中虚函数表存放位置的思考

    其实这是我前一段时间思考过的一个问题,是在看<深入探索C++对象模型>这本书的时候我产生的一个疑问,最近在网上又看到类似的帖子,贴出来看看: 我看到了很多有意思的答案,都回答的比较好,下面 ...

  3. C++对象的内存布局以及虚函数表和虚基表

    C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...

  4. C++虚函数表解析(图文并茂,非常清楚)( 任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法)good

    C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术 ...

  5. 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)

    本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类 ...

  6. C++类成员空间分配和虚函数表

    最近在自学python,看到继承和类,就顺便复习了C++的类和继承等方面的知识. 先看Base基类 class Base { private: virtual void display() { cou ...

  7. [C++] Vtable(虚函数表)

    Vtable(虚函数表)

  8. C++ 虚函数表解析

    转载:陈皓 http://blog.csdn.net/haoel 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实 ...

  9. C++虚函数表原理

    C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指 向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技 ...

随机推荐

  1. js获取url传递得参数

    方法一:正则法 function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(& ...

  2. week02 课堂作业

    测试一:(点此看原题目) 运行结果: 测试二:(点此看原题目) 运行结果: 测试三:(点此看原题目) 运行结果:

  3. javascript ----> Immediately-Invoked Function Expression (IIFE)(翻译)

    http://benalman.com/news/2010/11/immediately-invoked-function-expression/ 如果你没有注意到,我对术语有一点点坚持. 所以,在听 ...

  4. English Voice of <<Beautiful now>>

    Beautiful Now  -Zedd & Jon Bellion I see what you're wearing, there's nothing beneath it 我看见了你身着 ...

  5. LeetCode--415--字符串相加

    问题描述: 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和. 注意: num1 和num2 的长度都小于 5100. num1 和num2 都只包含数字 0-9. num1 和nu ...

  6. You Don't Know JS: Scope & Closures (第3章: 函数 vs 块作用域)

    第二章,作用域由一系列的bubbles组成.每一个都代表了一个container或bucket,装着被声明的identifiers(variables, functions).这些bubbles相互嵌 ...

  7. BFS+二进制状态压缩 hdu-1429

    好久没写搜索题了,就当练手吧. vis[][][1025]第三个维度用来维护不同key持有状态的访问情况. 对于只有钥匙没有对应门的位置,置为'.',避免不必要的状态分支. // // main.cp ...

  8. 动态加载DataGrid表头及数据

    初始化表头 js生成前端 /*初始化表头*/ function initDataGridTitle(id) { $.ajax({ url: '/${appName}/report/***/***', ...

  9. linux 查看日志命令

    linux中命令cat.more.less均可用来查看文件内容, 区别:cat是一次性显示整个文件的内容,还可以将多个文件连接起来显示,它常与重定向符号配合使用,适用于文件内容少的情况:more和le ...

  10. python--django-admin定制页面流程:

    django-admin定制页面流程: 1.自定义一个类:要继承 ModelAdmin class Cool(admin.ModelAdmin):    pass    2. 在注册时,表名后加 自定 ...