《深度探索C++对象模型》调用虚函数

简介:

如果一个类有虚函数,那么这个类的虚函数会被放在一个虚函数表里面, 使用这个类声明的对象中,会有一个指向虚函数表的指针,当使用指向 这个对象的指针或者这个对象的引用调用一个虚函数的时候,就会从虚函数表中去 查找该函数,然后对其进行调用。

如果有如下的类:

复制代码
class A {
    public :
        int m_a;
        A() {}
        ~A() {}

        virtual void test() { cout << "A info : " << __LINE__ << " , " << __func__ << endl;}
};

class B : public A{
    public :
        int m_b;
        B() {}
        ~B() {}

        virtual void test() { cout << "B info : " << __LINE__ << " , " << __func__ << endl;}
};
复制代码

 

那么我们显示出一个 B 类对象的内存状态, 这个类声明的对象的内存布局会是下面这样:

复制代码
#ifdef __x86_64__
cout << "__x86_64__" << endl;
#else 
cout << "not 64" << endl;
#endif

cout << "sizeof(B) = " << sizeof(B) << endl;
cout << "sizeof(int) = " << sizeof(int) << endl;

B b;
b.m_a = 0x01010101;
b.m_b = 0x02020202;

show_mem(&b, sizeof(b));
复制代码

 

执行结果:

复制代码
__x86_64__
sizeof(B) = 16
sizeof(int) = 4
addrress      : 00 f8 cc fa ff 7f 00 00 
memory layout : 00 0f 40 00 00 00 00 00 01 01 01 01 02 02 02 02
复制代码

我们看到,拥有两个 int 成员变量的 b 对象,它占用的内存大小却不是 两个 sizeof(int) 的和 8,而是16。很明显,另外8个字节就是存放虚函数表地址 的了,因为目前使用的是64位系统,指针占用的空间是64 bit。

那么,我们现在知道了一个对象的内存布局后,就可以采取 "非法" 手段 调用一个虚函数了。比如下面这段代码:

复制代码
#ifdef __x86_64__ 
typedef unsigned long int  POINT_SIZE;
#else
typedef int POINT_SIZE;
#endif

typedef void(*Fun)();

//获取对象的地址
POINT_SIZE *po = (POINT_SIZE *)&b;

//获取这个对象前 8 个字节的值,这个值是虚函数表的地址
POINT_SIZE tbl = po[0];

//把这个值转换为地址类型,也就是虚函数表的地址
POINT_SIZE *ptbl = (POINT_SIZE *)tbl;

int pos = 0;
//虚函数表的第一表项就是第一个虚函数的函数地址,
//这里将其转换为函数类型
Fun pfun = (Fun)(ptbl[pos]);

//调用这个函数
pfun();
复制代码

 

调用的结果是:

B info : 38 , test

 

说明调用了 B 类的虚函数,内存布局如下:

这样,我们使用非常规手段就可以调用一个类的虚函数了。



本文转自郝峰波博客园博客,原文链接:http://www.cnblogs.com/fengbohello/p/6261873.html,如需转载请自行联系原作者

相关文章
|
18天前
|
C++
9. C++虚函数与多态
9. C++虚函数与多态
22 0
|
26天前
|
设计模式 编解码 算法
【C/C++ 虚函数以及替代方案】C++ 虚函数的使用开销以及替代方案(三)
【C/C++ 虚函数以及替代方案】C++ 虚函数的使用开销以及替代方案
41 0
|
26天前
|
存储 设计模式 编译器
【C/C++ 虚函数以及替代方案】C++ 虚函数的使用开销以及替代方案(一)
【C/C++ 虚函数以及替代方案】C++ 虚函数的使用开销以及替代方案
52 0
|
3月前
|
存储 C++ 容器
第十四章:C++虚函数、继承和多态详解
第十四章:C++虚函数、继承和多态详解
27 0
|
3月前
|
C++
C++析构函数定义为virtual虚函数,有什么作用?
C++析构函数定义为virtual虚函数,有什么作用?
28 0
|
24天前
|
算法 安全 编译器
【C++ 关键字 override】C++ 重写关键字override(强制编译器检查该函数是否覆盖已存在的虚函数)
【C++ 关键字 override】C++ 重写关键字override(强制编译器检查该函数是否覆盖已存在的虚函数)
25 0
|
24天前
|
算法 Java 编译器
【C++ 关键字 virtual 】C++ virtual 关键字(将成员函数声明为虚函数实现多态
【C++ 关键字 virtual 】C++ virtual 关键字(将成员函数声明为虚函数实现多态
25 0
|
20天前
|
存储 程序员 编译器
【C++ 模板类与虚函数】解析C++中的多态与泛型
【C++ 模板类与虚函数】解析C++中的多态与泛型
46 0
|
25天前
|
存储 算法 编译器
【C++入门到精通】C++入门 —— 多态(抽象类和虚函数的魅力)
多态是面向对象编程中的一个重要概念,指的是同一个消息被不同类型的对象接收时产生不同的行为。通俗来说,**就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态**。
43 0
|
26天前
|
存储 编译器 程序员
【C/C++ 虚函数以及替代方案】C++ 虚函数的使用开销以及替代方案(二)
【C/C++ 虚函数以及替代方案】C++ 虚函数的使用开销以及替代方案
58 0