C++单继承、多继承情况下的虚函数表分析
C++的三大特性之一的多态是基于虚函数实现的,而大部分编译器是采用虚函数表来实现虚函数,虚函数表(VTAB)存在于可执行文件的只读数据段中,指向VTAB的虚表指针(VPTR)是包含在类的每一个实例当中。当使用引用或指针调用虚函数时,首先通过VPTR找到VTAB,然后通过偏移量找到虚函数地址并调用。
本文参考:1.http://blog.lucode.net/programming-language/cpp-vtab-and-call-convention.html
2.https://blog.csdn.net/tangaowen/article/details/5830803
3.《深度探索C++对象模型》
一、单继承
#include<iostream>
#include <stdio.h>
using namespace std;
class A {
public:
void func() {
cout << "A::func()" << endl;
}
virtual void func1() {
cout << "A::func1(): " << endl;
} virtual void func3() {
cout << "A::func3(): " << endl;
}
}; class B: public A {
public:
virtual void func() {
cout << "B::func()" << endl;
}
virtual void vfunc() {
cout << "B::vfunc()" << endl;
}
void func1() {
cout << "B::func1(): " << endl;
}
};
int main() {
typedef void (*Fun)(void);
B a; Fun *fun = NULL;
fun = (Fun*) ((int *) *(int *) &a);
// fun = *(Fun **) &a;
fun[]();
fun[]();
fun[]();
fun[](); return ;
}
运行结果:
B::func1():
A::func3():
B::func()
B::vfunc()
二、多重继承
#include<iostream>
#include <stdio.h>
using namespace std;
class B1 {
public:
virtual void barB1() {cout << "B1::bar" << endl;}
virtual void fooB1() {cout << "B1::foo" << endl;}
}; class B2 {
public:
virtual void barB2() {cout << "B2::bar" << endl;}
virtual void fooB2() {cout << "B2::foo" << endl;}
}; class D : public B1, B2 {
public:
void fooB1() {cout << "D::foo" << endl;}
void barB2() {cout << "D::bar" << endl;}
}; typedef void (*Func)();
int main() {
D tt;
Func* vptr1 = *(Func**)&tt;
Func* vptr2 = *((Func**)&tt + ); vptr1[]();
vptr1[]();
vptr1[]();
cout<<"\\\\\\\\\\\\"<<endl;
vptr2[]();
vptr2[](); return ;
}
运行结果:
B1::bar
D::foo
D::bar
\\\\\\
D::bar
B2::foo
结论:
多重继承会有多个虚函数表,几重继承,就会有几个虚函数表。这些表按照派生的顺序依次排列,如果子类改写了父类的虚函数,那么就会用子类自己的虚函数覆盖虚函数表的相应的位置,如果子类有新的虚函数,那么就添加到第一个虚函数表的末尾。
再简单总结一下 覆盖 隐藏 重载 的区别:
覆盖 是C++虚函数的实现原理,基类的虚函数被子类重写,要求函数参数列表相同;
隐藏 是C++的名字解析过程,分两种情况,基类函数有virtual,参数列表不同,或基类函数没有virtual,无论参数列表是否相同。此时基类指针指向基类实例则调用基类函数,指向子类则调用子类函数。
重载 是在同一命名空间中根据参数对同名函数的区别。
// 我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3ph7kzdx2saoo
C++单继承、多继承情况下的虚函数表分析的更多相关文章
- c++ 继承类强制转换时的虚函数表工作原理
本文通过简单例子说明子类之间发生强制转换时虚函数如何调用,旨在对c++继承中的虚函数表的作用机制有更深入的理解. #include<iostream> using namespace st ...
- C++ 虚函数表解析 继承
C++ 虚函数表解析 陈皓 http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父 ...
- C++ 虚函数表 单继承
本文研究单继承情况下,c++对象的虚函数表的具体情况. 假设有两个类A,B, 其中B由A派生出来,A含有虚函数fun1,B含有虚函数fun2. 测试的代码如下: #include<iostrea ...
- C++多态中虚函数表合并与继承问题
多态: C++的多态是通过一张虚函数表(Virtual Table)来实现的,简称为 V-Table.在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承.覆写的问题,保证其真实反应实际的函数. ...
- C++ 由虚基类 虚继承 虚函数 到 虚函数表
//虚基类:一个类可以在一个类族中既被用作虚基类,也被用作非虚基类. class Base1{ public: Base1(){cout<<"Construct Base1!&q ...
- 详谈C++虚函数表那回事(一般继承关系)
沿途总是会出现关于C++虚函数表的问题,今天做一总结: 1.什么是虚函数表: 虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-Table. ...
- C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局
1. 使用继承的虚函数表: 如果不涉及多重继承,每个类只有1个虚函数表,当子类继承父类后,子类可以自己改写和新增虚函数,如下图所示: 子类重写 func_1 后,子函数的 func_1 将会有新的逻辑 ...
- 异常情况下的Activity生命周期分析
情况1:资源相关的系统配置发生改变 资源相关的系统配置发生改变,举个栗子.当前Activity处于竖屏状态的时候突然转成横屏,系统配置发生了改变,Activity就会销毁并且重建,其onPause, ...
- C++内存中的封装、继承、多态(下)
上篇讲述了内存中的封装模型,下篇我们讲述一下继承和多态. 二.继承与多态情况下的内存布局 由于继承下的内存布局以及构造过程很多书籍都讲得比较详细,所以这里不细讲.重点讲多态. 继承有以下这几种情况: ...
随机推荐
- java 字节码指令集
This is a list of the instructions that make up the Java bytecode, an abstract machine language that ...
- git常用总结
git 基本配置 安装git yum -y install git git全局配置 git config --global user.name "lsc" #配置git使用用户 g ...
- asp.net core 2.2 生产环境直接更新View页面并立即生效
有的时候我们会直接在生产环境上更新页面文件,比如更改了JS代码,CSS代码或页面的文案,布局等.这种没有改到后台代码的情况一般就是直接发布页面文件了,在asp.net core 2.2以前的版本(没有 ...
- Python中的函数及函数参数的使用
函数:一个工具,随调随用 降级代码冗余 增加代码的复用性,提高开发效率,为了不成为cv战士 提高程序扩展性 函数有两个阶段:定义阶段,调用阶段. 定义时:只检查函数体内代码语法,不执行函数体内代码. ...
- CentOS 常用命令合集
tail -f ../logs/catalina.out 在Tomcat中的bin目录下查看Tomcat日志 ps -ef|grep java 查看Tomcat服 ...
- HDU 1286:找新朋友(欧拉函数)
http://acm.hdu.edu.cn/showproblem.php?pid=1286 题意:中文. 思路:求欧拉函数. #include <cstdio> #include < ...
- Java面试总结(一)
1.equals和==和hashcode “==”是运算符,比较两个变量的值是否相等 equals是Object类的方法.比较两个对象是否相等 hashcode是Object类的方法,返回一个 ...
- android_alertDialog
主文件 package cn.com.sxp;import android.app.Activity;import android.app.AlertDialog;import android.con ...
- 【webpack系列】webpack4.x入门配置基础(一)
一.前言 webpack在不断的迭代优化,目前已经到了4.29.6.在webpack4这个版本中,做了很多优化,引入了很多特性,将获得更多模块类型,.mjs支持,更好的默认值,更为简洁的模式设置,更加 ...
- Shiro authentication for Apache Zeppelin
Overview Apache Shiro is a powerful and easy-to-use Java security framework that performs authentica ...