有关C++多态的一些测试
由于一直对C++的多态心存疑虑,今天想彻底弄明明一点,所以做了一些测试,将结果拿出来同大家一起分享。测试在VC6下进行,以下是测试时用的继承关系以及虚函数的重写情况(不能贴图,可惜,可能贴源码了):
class BaseA
{
public:
BaseA();
~BaseA();
virtual void printme();
virtual void printme1();
};
class BaseB : public BaseA
{
public:
BaseB();
~BaseB();
virtual void printme();
};
class BaseC :public BaseA
{
public:
BaseC();
~BaseC();
virtual void printme();
};
class BaseD:public BaseB,BaseC
{
public:
BaseD();
~BaseD();
virtual void printme();
virtual void dxx();
};
class BaseF : public BaseD
{
public:
BaseF();
~BaseF();
virtual void printme1();
};
1、如果继承体系里没有C类,即粗线的单重继承,则以下测试代码是可行的(先从类实例地址的开始处取得指向vtable的指针,vtable是一个指针数组,每一个值都指向一个虚函数,因此可以顺序递增去执行每一个方法):
void *getp (void* p)
{
return (void*)*(unsigned long*)p;
}
fun getfun (BaseD* obj, unsigned long off)
{
void *vptr = getp(obj);
unsigned char *p = (unsigned char *)vptr;
p += sizeof(void*) * off;
return (fun)getp(p);
}
void testv()
{
BaseF *p = new BaseF;
fun f = getfun(p, 0);
(*f)();
f = getfun(p, 1);
(*f)();
}
输出为:
is BaseD here
is BaseF here 1
虚函数表图如下:
---------图没贴上来-------------------
b1
BaseD
BaseB
BaseA
_vfptr
[0] BaseD::printme(void)
[1] BaseF::printme1(void)
其中:BaseF *b1 = new BaseF;
此时,如果你想直接调用A的printme1方法,可用如下方法:
b1->BaseA::printme();
2、如果在继承层次中加入C类,则有了多重继承,以下将是b1的虚函数图:
---------图没贴上来-------------------
b1 0x02193a10
BaseD
BaseB
BaseA
_vfptr 0x004380fc const BaseF::’vftable’{for’baseB’}
[0] 0x00401154 BaseD::printme(void)
[1] 0x004010af BaseF::printme1(void)
BaseC
BaseA
_vfptr 0x004380f0 const BaseF::’vftable’{for’baseC’}
[0] 0x00401172 [thunk]:BaseD::printme’adjustor{4}’(void)
[1] 0x0040116D[thunk]:BaseF::printme1’adjustor{4}’(void)
(此时用上面的代码手动调用虚函数将会出错,具体内存是如何分布的,我没有去深入研究了)
可以看到,每一个继承分支都有不同的虚函数表,此时,如果你想用:
b1->BaseA::printme();
来调用A的方法,编译将通不过,告诉你会有歧义。而必须用:
((BaseC *)b1)->BaseA::printme();
来调用。
有关C++多态的一些测试相关推荐
- 【Kotlin】Kotlin 面向对象 ( 类 | 成员变量 | 成员方法 | 封装 | 继承 | 多态 )
文章目录 I . 创建简单类 ( 整型字段 ) II . 创建简单类 ( 整型字段 + 字符串字段 ) III . 类方法定义 IV . 封装 V . 继承 VI . 多态 与 抽象类 I . 创建简 ...
- java的知识点13——多态、对象的转型(casting)、final关键字、抽象方法和抽象类、接口的作用、如何定义和使用接口?、接口的多继承、面向接口编程
多态 多态指的是同一个方法调用,由于对象不同可能会有不同的行为.现实生活中,同一个方法,具体实现会完全不同. 多态的要点: 1. 多态是方法的多态,不是属性的多态(多态与属性无关). 2. 多态的存在 ...
- 重构—改善既有代码的设计4——构筑测试体系
编写优良的测试程序,可以极大提高编程速度,即使不进行重构也一样. 自测试代码的价值: 程序员花时间最多的是用来调试:修复错误通常是比较快的,找出错误却是恶梦一场:当修好一个错误,总会有另一个错误出现, ...
- 1-11 Java 多态、类型转型
文章目录 1.业务场景 2.多态调用 3.多态应用 1)业务场景 2)传统代码实现 3)问题思考 4)多态代码实现 4.向上.向下转型 1)举例 2)小总结 面向对象特征:抽象.封装.继承和多态,这些 ...
- java学习笔记day09 final、多态、抽象类、接口
java学习笔记day09 思维导图 final . 多态 . 抽象类 . 接口 (都很重要) 一.final 二.多态 多态中的成员访问特点⭐ [P237] 多态的好处 [P239] 多态的弊端 向 ...
- java:多态详解,以及对象的向上和向下转型
大家好,兔胆包天我又来啦,今天给大家分享的是多态,多态最主要的是父类引用指向子类对象,还是老办法,直接上代码,代码中注解的很详细哦. 这是第一个代码: //测试多态 public class Anim ...
- Educoder- 《JAVA从小白到大牛》(第二章)2-3 Java面向对象 - 封装、继承和多态的综合练习
提示:本文章为个人学习记录,仅供参考学习,禁止转载,支持交流与讨论. 文章目录 第1关:通关任务一 任务描述 相关知识 面向对象思想 封装 继承 `super()`和`this()` 编程要求 测试说 ...
- Java面向对象 - 封装、继承和多态的综合练习
面向对象的三个基本特征: 封装,就是把客观的事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的信息隐藏.隐藏实现细节,使得代码模块化. 继承,可以使用现有类的所有功能 ...
- 【Java SE】面向对象三大特性之多态
何为多态? 多态,通俗一点说就是在完成某一个行为的时候,不同的对象会产生不同的形态. 比如说:打印机在完成打印行为的时候,可以根据不同的对象打印不同的类型,有黑白,有彩色等等,打印的结果是不一样的. ...
最新文章
- Zend Framework中,执行自定义sql语句
- spring原理案例-基本项目搭建 01 spring framework 下载 官网下载spring jar包
- 数学建模之图像处理---颜色建模
- 批改网作文提交时分析不出来_小学生作文写作从哪些方面提高呢?
- 解决HttpServletResponse输出中文乱码问题
- MongoDB-pymongo
- 实验12 编写0号中断的处理程序
- 诺基亚手机新品发布定档 6 月 11 日!Nokia C20 Plus 即将到来
- 海康相机回调方式理一下
- jackson的简单实用实例(json)
- python以追加方式打开文件 线程安全吗_Python多线程同步---文件读写控制方法
- Java 打印对象的地址
- ant构建异常UNEXPECTED TOP-LEVEL EXCEPTION com.android.dx.cf.iface.ParseException解决
- DNS的更新和ddns(动态域名解析)
- 17-chan原理1-创建
- 获取高薪职位的六个妙计
- matlab坐标旋转平移缩放,MATLAB实现RGB图像的平移、缩放和旋转
- 高低温磁场型霍尔效应测试仪的设计方案
- 第一个Ajax程序给我的下马威——xmlHttp的status=0?
- lammps模拟中tersoff势设置方法
热门文章
- 2021年信息系统项目管理师案例分析第二题讲解
- 软考准考证打印详细步骤(打印一张纸上)
- 信息系统项目管理师:第9章:项目人力资源管理-历年真题
- java基础知识1---面向对象及final,finally,finalize区别
- 《系统集成项目管理工程师》必背100个知识点-74CMO的具体工作
- MyBatis中动态sql实现时间范围比较的查询
- Vue实现仿音乐播放器11-实现访问百度音乐API实现播放音乐功能
- springboot-自动配置原理
- 在“软件工程:研究与实践”研讨会上关于UML Use-Case的开放空间讨论
- Dart微基准测试第一部分