C++ 关于类与对象在虚函数表上唯一性问题 浅析
【摘要】
非常多教材上都有介绍到虚指针、虚函数与虚函数表。有的说类对象共享一个虚函数表,有的说,一个类对象拥有一个虚函数表。还有的说,不管用户声明了多少个类对象,可是,这个VTABLE虚函数表仅仅有一个。也有的在说,每一个具有虚函数的类的对象里面都有一个VPTR虚函数指针,这个指针指向VTABLE的首地址,每一个类的对象都有这么一种指针。今天。我们就来解决问题,同一个类的不同对象,是不是拥有“同样”的虚函数表,这个同样是物理上的同样(内存地址)还是逻辑上的同样(数据结构)。本文现详述例如以下。
【正文】
虚指针:每一个含有虚方法(虚函数)对象里有虚表指针。指向虚表。
虚函数表:虚函数表是顺序存放虚函数地址的,虚表是顺序表,表里存放了虚函数的地址。
C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——假设有多层继承或是多重继承的情况下)。
这意味着我们通过对象实例的地址得到这张虚函数表。然后就能够遍历当中函数指针,并调用对应的函数。
【代码演示样例】
#include <iostream>
using namespace std; class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; } };
typedef void(*Fun)(void); int main()
{
Fun pFun = NULL;
Base obj_1,obj_2;
// obj_1 虚函数表 — 第一个函数
pFun = (Fun)*((int*)*(int*)(&obj_1));
pFun();
pFun = (Fun)*(((int*)*(int*)(&obj_1))+1);
pFun();
// 输出 虚函数表地址 与 虚函数表元素 的值
cout << "obj_1 虚函数表地址:" << (int*)(&obj_1) << endl;
cout << "obj_2 虚函数表地址:" << (int*)(&obj_2) << endl;
cout << "obj_1 虚函数表 — 第一个函数地址:" << (int*)*(int*)(&obj_1) << endl;
cout << "obj_2 虚函数表 — 第一个函数地址:" << (int*)*(int*)(&obj_2) << endl;
return 0;
}
/*
输出 :
Base::f
Base::g
obj_1 虚函数表地址:0018FF40
obj_2 虚函数表地址:0018FF3C
obj_1 虚函数表 — 第一个函数地址:0046F0AC
obj_2 虚函数表 — 第一个函数地址:0046F0AC
Press any key to continue
*/
【结论】
不同对象虚函数表表中元素是相等的。逻辑上是一样的,存放的都是类中虚函数的地址;
不同对象虚函数表的内存地址是不一样,物理上是不一样的,一个对象是一个新的表。
【相关推荐】
详见:C++ 虚函数表解析
详址:http://blog.csdn.net/haoel/article/details/1948051#comments
C++ 关于类与对象在虚函数表上唯一性问题 浅析的更多相关文章
- C++类成员空间分配和虚函数表
最近在自学python,看到继承和类,就顺便复习了C++的类和继承等方面的知识. 先看Base基类 class Base { private: virtual void display() { cou ...
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- C++ 类的存储方式以及虚函数表
一.C++成员函数在内存中的存储方式 用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间.按理说,如果用同一个类定义了10个对象,那么就 ...
- C++ Daily 《5》----虚函数表的共享问题
问题: 包含一个以上虚函数的 class B, 它所定义的 对象是否共用一个虚函数表? 分析: 由于含有虚函数,因此对象内存包含了一个指向虚函数表的指针,但是这个指针指向的是同一个虚函数表吗? 实验如 ...
- C++虚函数表
大家知道虚函数是通过一张虚函数表来实现的.在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承.覆盖的问题,其内容真是反应实际的函数.这样,在有虚函数的类的实例中,这个表分配在了这个实例的内存中 ...
- 对C++虚函数、虚函数表的简单理解
一.虚函数的作用 以一个通用的图形类来了解虚函数的定义,代码如下: #include "stdafx.h" #include <iostream> using name ...
- C++虚函数与虚函数表
多态性可分为两类:静态多态和动态多态.函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的. 每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说 ...
- 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数
一.多态 多态性是面向对象程序设计的重要特征之一. 多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态的实现: 函数重载 运算符重载 模板 虚函数 (1).静态绑定与动态绑 ...
- C++ 虚函数表与内存模型
1.虚函数 虚函数是c++实现多态的有力武器,声明虚函数只需在函数前加上virtual关键字,虚函数的定义不用加virtual关键字. 2.虚函数要点 (1) 静态成员函数不能声明为虚函数 可以这么理 ...
随机推荐
- Java的代码转C#
推荐个网站:点击打开链接 细节上有些小问题
- Lua 语法要点
table 默认键值都是从1开始 table array = { "A", "B" } array2 = array array[] = "D&quo ...
- ruby 发送邮件
产品构建.打包.部署完需要发送邮件通知相关人员进行验证.请看过程 #encoding:utf-8 require 'mail' #~ branch = ARGV.to_s.sub('[','').su ...
- arp_ignore和arp_announce内核参数
arp_announce : INTEGER 对网络接口上本地IP地址发出的ARP报文作出相应级别的限制. 0:本机所有IP地址都向任何一个接口通告ARP报文. 1:尽量仅向该网卡回应与该网段匹配的A ...
- AngularJs MVC 详解
为什么在前端也需要MVC 1.代码规模越来越大,切分职责是大势所趋 2.为了复用 3.为了后期维护方便 MVC的目的是为了模块化和复用 前端实现MVC的困难 1.操作DOM必须等整个页面加载完 2.多 ...
- EPEL 安装源
EPEL 安装源 EPEL 是 Extra Packages for Enterprise Linux 的缩写(EPEL),是用于 Fedora-based Red Hat Enterprise Li ...
- HDU 3395 Special Fish(拆点+最大费用最大流)
Special Fish Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- BZOJ-1038 [ZJOI2008]瞭望塔
先求半平面交,然后建塔的地方肯定是在半平面交的交点上或者是在地面线段的交点上. #include <cstdlib> #include <cstdio> #include &l ...
- 使用mapMutations扩展写法后参数传递的办法
在没使用扩展办法的时候,在组件当中通过下面方式进行传参 testMethods(data) { this.$store.commit("add",data) } 而使用了扩展函数了 ...
- 【02】 Vue 之 数据绑定
2.1. 什么是双向绑定? Vue框架很核心的功能就是双向的数据绑定. 双向是指:HTML标签数据 绑定到 Vue对象,另外反方向数据也是绑定的.通俗点说就是,Vue对象的改变会直接影响到HTML的标 ...