IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 验证C++中的虚函数表的存在 -> 正文阅读

[游戏开发]验证C++中的虚函数表的存在

///从网上抄来的,做了点修改,能正确运行出来而已
#include <stdio.h>
#include <iostream>
using namespace std;

///基类,有2个成员变量width和height,有2个虚函数和一个成员函数
class Shape
{
public:
?? ?Shape(int a = 0, int b = 0)
?? ?{
?? ??? ?width = a;
?? ??? ?height =b;
?? ?}
?? ?
?? ?virtual int area()
?? ?{
?? ??? ?printf("Parent class area:\n");
?? ??? ?return 0;
?? ?}
?? ?
?? ?virtual void sayHello()
?? ?{
?? ??? ?printf("Shape..\n");
?? ?}
?? ?
?? ?void bar()
?? ?{
?? ??? ?printf("bar fun width:%d\n", width);
?? ?}
?? ?
protected:
?? ?int width, height;
};

///Shape子类,继承了Shape的width和height,重写了虚函数area和sayHello,重新定义了一个虚函数Call,相当于有3个虚函数
class Rectangle:public Shape
{
public:
?? ?Rectangle(int a = 0, int b = 0) : Shape(a, b){}
?? ?int area()
?? ?{
?? ??? ?printf("Rectangle class area:\n");
?? ??? ?return width * height;
?? ?}

?? ?virtual void sayHello()
?? ?{
?? ??? ?printf("Rectangle..\n");
?? ?}
?? ?
?? ?virtual void Call()
?? ?{
?? ??? ?printf("Rectangle Call....\n");
?? ?}
?? ?
};

///Shape子类,继承了Shape的width和height,重写了虚函数area和sayHello,重新定义了一个虚函数Call,相当于有3个虚函数
class Triangle:public Shape
{
public:
?? ?Triangle(int a = 0, int b = 0) : Shape(a, b){}
?? ?int area()
?? ?{
?? ??? ?printf("Triangle class area:\n");
?? ??? ?return width * height / 2;
?? ?}

?? ?virtual void sayHello()
?? ?{
?? ??? ?printf("Triangle..\n");
?? ?}
?? ?
?? ?virtual void Call()
?? ?{
?? ??? ?printf("Triangle Call....\n");
?? ?}
};

///多肽的调用接口
void test(Shape* shape)
{
?? ?shape->bar();
?? ?shape->area();
?? ?shape->sayHello();
}

class Shape1
{
public:
?? ?Shape1(int a = 0, int b = 0)
?? ?{
?? ??? ?width = a;
?? ??? ?height =b;
?? ?}
?? ?
?? ? int area()
?? ?{
?? ??? ?printf("Parent class area:\n");
?? ??? ?return 0;
?? ?}
?? ?
?? ? void sayHello()
?? ?{
?? ??? ?printf("Shape..\n");
?? ?}
?? ?
?? ?void bar()
?? ?{
?? ??? ?printf("bar fun width:%d\n", width);
?? ?}
?? ?
protected:
?? ?int width, height;
};

void test2(Shape* shape)
{
?? ?printf("\n----\n");
?? ?
?? ?typedef void (*BAR_FUN)(void*);
?? ?typedef int (*AREA_FUN)(void*);
?? ?typedef void (*SAYHELLO_FUN)(void*);
?? ?typedef void (*CALL_FUN)(void*);
?? ?typedef void* ADDRESS;
?? ?
?? ?BAR_FUN bar_fun = (BAR_FUN)(&Shape::bar); ///bar成员函数为非虚函数
?? ?bar_fun((void*) shape); ///调用bar函数,需要传入this指针就是shape
?? ?
?? ?///前面8个字节存放的是虚函数表,先将虚表首地址(二级指针)强制转换成void** 类型
?? ?///虚表是二级指针,在首地址处
?? ?ADDRESS* vtable_addr = *((ADDRESS**)(shape));///先将二级指针转换成一级指针,实现函数调用
?? ?ADDRESS ptr = *(vtable_addr);///先获取到虚表的首地址
?? ?AREA_FUN area_fun = (AREA_FUN)ptr; ///把虚函数area的首地址赋值给area_fun
?? ?
?? ?///vtable_addr + 1的原因是获取sayhello_fun函数地址
?? ?SAYHELLO_FUN sayhello_fun = (SAYHELLO_FUN)*(vtable_addr+1);
?? ?
?? ?///vtable_addr + 2的原因是获取Call函数地址
?? ?CALL_FUN ?call_fun = (CALL_FUN)*(vtable_addr+2);
?? ?
?? ?area_fun((void*)shape);?? ??? ??? ??? ?///传入this指针shape
?? ?sayhello_fun((void*)shape);?? ??? ??? ?///传入this指针shape
?? ?call_fun((void*)shape);?? ??? ??? ??? ?///传入this指针shape
?? ?
?? ?printf("\n----\n");
?? ?
}

int main()
{
?? ?cout << sizeof(Shape) << endl;?? ??? ??? ??? ?///16个字节
?? ?cout << sizeof(Triangle) << endl;?? ??? ??? ?///16个字节
?? ?cout << sizeof(Rectangle) << endl;?? ??? ??? ?///16个字节
?? ?cout << sizeof(Shape1) << endl;?? ??? ??? ??? ?///8个字节(没有加virtual关键字)
?? ?///说明写了virtual,C++编译器多分配了8个字节存放虚表,进行多肽,
?? ?///int width, height占了8个字节
?? ?
?? ?///多肽
?? ?Shape* shape = new Triangle(3, 4);
?? ?///test(shape);
?? ?test2(shape);
?? ?delete shape;
?? ?
?? ?///多肽
?? ?shape = new Rectangle(5, 6);
?? ?///test(shape);
?? ?test2(shape);
?? ?delete shape;
?? ?
?? ?return 0;
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:21:40  更:2022-04-06 16:24:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 20:12:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码