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学习之字符串类
String在Java中是一个类类型(非主类型),是一个不可被继承的final类,而且字符串对象是一个不可变对象.声明的String对象应该被分配到堆中,声明的变量名应该持有的是String对象的引用 ...
- 聊聊、SpringBoot 静态资源访问
SpringBoot 1.X 版本和 SpringBoot 2.X 版本在静态资源访问上有一些区别,如果直接从 1.X 升级到 2.X 肯定是有问题的.这篇文章就来讲讲这方面问题,也是项目中的坑. 先 ...
- drools6
<dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artif ...
- bzoj1086【SCOI2005】王室联邦
题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1086 sol :这题水水啊,直接大力DFS就行了 首先当且仅当x<B时无解 对于以x为 ...
- powerdesign设置字体大小
http://www.2cto.com/database/201406/308923.html
- get****Context各个方法分析
1 getApplicationContext分析 该方法为contextImpl类的方法,返回一个ApplicationContext.方法代码为: public Context getApplic ...
- vue2搭建简易spa
使用vue-cli来配置webpack,webpack是一个打包工具,使程序模块化 全局安装vue-cli: npm install -g vue-cli 安装好后,使用vue-cli脚手架配置web ...
- 勒索病毒 -- “永恒之蓝”NSA 武器免疫工具
“永恒之蓝”NSA 武器免疫工具 针对 445 端口:445端口是一个毁誉参半的端口,他和139端口一起是IPC$入侵的主要通道.有了它我们可以在局域网中轻松访问各种共享文件夹或共享打印机,但也正是因 ...
- JDBC连接池&DBUtils使用
使用连接池改造JDBC的工具类: 1.1.1 需求: 传统JDBC的操作,对连接的对象销毁不是特别好.每次创建和销毁连接都是需要花费时间.可以使用连接池优化的程序. * 在程序开始的 ...
- python字符串加密与反解密
在生产中会遇到很多情况是需要加密字符串的(如访问或存储密码)这些需求造就了需要字符串加密,以及反解密的问题,推荐两种方法来实现,下附代码: #!/usr/bin/env python3 # -*- c ...