C++虚函数和虚函数表
在上面的博文中描述了基类中存在虚函数时,基类和派生类中虚函数表的结构。
在派生类也定义了虚函数时,函数表又是怎样的结构呢?
先看下面的示例代码:
#include <iostream> using namespace std; class A
{
public:
virtual void funcA(){ cout<<"A"<<endl; }
}; class B
{
public:
virtual void funcB(){ cout<<"B"<<endl; }
}; class C : public A, public B
{
public:
virtual void funcC(){ cout<<"C"<<endl; }
}; int main()
{
C c;
cin.get();
}
class A 和 class B 都有一个虚函数,然后 class C 继承 A 和 B。在VS2010中,查看变量:

如图所示,局部变量中只显示了从 A 和 B 继承来的虚函数表地址。那么 C 自己的虚函数呢?
首先查看 A 虚函数表地址:

可以看到,虚函数表中的前4个字节就是 A 中虚函数的地址(红色框)。同时后面又紧跟着4个有内容的字节,然后才是表示虚函数表结束的4个0。
可以猜测,这应该就是 C 的虚函数地址。再来看一下 B 的虚函数表:

可以看到,虚函数表中只有 B 的虚函数这一个地址。为了证实上面的猜测,将函数指针从 A::funcA 向后递增一次,应该就是对 C::funC的调用:
int main()
{
typedef void(*pfun)(); C c;
auto p = &c; auto funcA = (pfun)**((int**)p);
funcA(); // 调用 A::funcA auto funcC = (pfun)*(*((int**)p) + );
funcC(); // 调用 C::funcC cin.get();
}
输出结果:
证实了我们的猜测。
如果在增加一个 class D 继承 C 呢?
class D : public C
{
virtual void funcD() {}
}; int main()
{
D d; cin.get();
}
变量:

和 C 中展示的一样,只有两个虚函数表。
内存:

可以看到,在 A::funcA 后还有两个地址,可以推测就是 C::funcC 和 D::funcD 的地址了。
总结:
1、在多继承中,派生类的虚函数表的个数由它所继承的“顶层的”基类的个数决定:有多少个这样的基类,就有多少个虚函数表。
2、派生类自己的虚函数被追加到第一个虚函数表的后面。
例如下面的继承:

假设每个类 X 都有一个 funcX 虚函数,那么G中虚函数和虚函数表如下:

C++虚函数和虚函数表的更多相关文章
- C++虚函数及虚函数表解析
一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Functio ...
- C++ 由虚基类 虚继承 虚函数 到 虚函数表
//虚基类:一个类可以在一个类族中既被用作虚基类,也被用作非虚基类. class Base1{ public: Base1(){cout<<"Construct Base1!&q ...
- 20140321 sizeof 虚函数与虚函数表 静态数组空间 动态数组空间 位字段
1.静态的数组空间char a[10];sizeof 不能用于1:函数类型 2:动态的数组空间new3:位字段 函数类型:int fun();sizeof(fun())计算的是返回类型的大小,并不是函 ...
- c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解
静态多态.动态多态 静态多态:程序在编译阶段就可以确定调用哪个函数.这种情况叫做静态多态.比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数.动态多态:在运行期间才可以确定最终调用的 ...
- 为何JAVA虚函数(虚方法)会造成父类可以"访问"子类的假象?
首先,来看一个简单的JAVA类,Base. 1 public class Base { 2 String str = "Base string"; 3 protected vo ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
- virtual之虚函数,虚继承
当类中包含虚函数时,则该类每个对象中在内存分配中除去数据外还包含了一个虚函数表指针(vfptr),指向虚函数表(vftable),虚函数表中存放了该类包含的虚函数的地址. 当子类通过虚继承的方式从父类 ...
- C++纯虚函数、虚函数、实函数、抽象类,重载、重写、重定义
首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不 ...
- 虚函数&纯虚函数&抽象类&虚继承
C++ 虚函数&纯虚函数&抽象类&接口&虚基类 1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过 ...
随机推荐
- win7 winsxs精简 cmd 脚本之 再次 改进版
dos时代菜鸟发表于 2012-7-24 http://bbs.wuyou.net/forum.php?mod=viewthread&tid=255200&highlight=win7 ...
- 红包demo
嘿嘿,红包demo import random dic={} lis=['KeLan','MonKey','Dexter','Superman','Iron Man','Robin'] def red ...
- c++11的右值引用、移动语义
对于c++11来说移动语义是一个重要的概念,一直以来我对这个概念都似懂非懂.最近翻翻资料感觉突然开窍,因此记下.其实搞懂之后就会发现这个概念很简单,并无什么高深的地方. 先说说右值引用.右值一般指的是 ...
- getParameterMap()的返回值为Map<String, String[]>,从其中取得请求参数转为Map<String, String>的方法如下:
直接遍历报错:[Ljava.lang.String;@44739f3f Map<String, String> tempMap = new HashMap<String, Strin ...
- django中css问题
django中加载的css,js,图片其中js和图片可以加载出来,而css没有效果.原因如下: 这是因为你安装的某些IDE 或者其他更改了注册表导致的系统的注册表\HKEY_CLASSES_ROOT\ ...
- Java-用switch判断季节
import java.util.*;class Demo3 { public static void main(String[] args) { //需求 :输入一个月份 ,判断月份属于哪一个季节 ...
- HTML5中引入的关键特性
新特性 描述 accesskey 定义通过键盘访问元素的快捷键 contenteditable 该特性设置为true时,浏览器应该允许用户编辑元素的内容.不指定变化后的内容如何保存 contextme ...
- VPN安装后报错:Reason442 & Error56
VPN安装后一直报错,同样的32位安装包别人安装是正常,自己安装就不正常了,考虑到是自己电脑配置的问题. 经过一番努力,解决了问题,下面就本次解决过程做一个小小的总结. (1)确保VPN Servic ...
- Codility Tree Height
public class HeightOfTreeSolution { static int height=-1; public int solution(Tree T) { // write you ...
- Mysql 拼接字段查询语句和join查询拼接和时间查询
个人平时记录的,有点乱 1.修改时间字段,如果时间字段的类型是date或者是datetime类型的 update 表名 set 时间字段 = DATE_FORMAT(NOW(),'%Y-%m-%d % ...