`

解析c++静态联编和类的成员函数调用

 
阅读更多

只要学了C++的人,肯定知道静态联编和动态联编,如果你不知道,ok那你学习之路还长。简单的静态联编的东西就不说了。先看下面程序。

class AA{
public:
void result()
{
std::cout << "Surprise?" << std::endl;
};
};
int main()
{
AA *p = NULL;
p->result();
system("Pause");
return 0;
}

上面程序运行会报错吗?

——————————————————————

如果你说运行一切正常并知道原因,ok。那就别往下看了,时间就是金钱。

确实,这个运行正常并输出 Surprise? 不信?你copy过去运行下试试。为啥啊。明明指针p的值是NULL,而你使用NULL指针去调用成员函数,明明会报内存错误的瑟。书上不是说了不能使用 NULL指针吗?嘿嘿,没错,确实不能使用NULL指针,但是这里,程序根本就没有用指针p的值,而是仅仅用到了它的类型做静态束定而已。

要解此题首先要明确两个问题。

1、静态联编的原理;2、成员函数的代码在运行期只有一份拷贝。

静态联编简单的说就是在编译期就已经确定了要调用哪个函数了,这里的result()就是。同时要知道,类的成员函数在运行期只有一份拷贝在内存,不管类的实例有多少个,成员函数始终只有一份代码在内存,因此只要知道类的指针的类型之后,就可以定位到函数的入口地址,根本不关心该指针指向的是一个什么东西。成员函数和成员变量不一样,非静态成员变量是跟随类的实例走的。

ok,明白上面两个问题之后,这个事情就好解决了。直接上汇编吧。

汇编如下:

AA *p = NULL;
00411ACE mov dword ptr [p],0
p->result();
00411AD5 mov ecx,dword ptr [p]
00411AD8 call AA::result (41105Ah)

清楚了吧。在执行p->result()的时候只是把p的值移动到了一个暂存器里面,但是并没有用到这个值,后面就直接调用AA::result函数了,0x41105A正是该函数的入口地址。

ok,好了。不仅可以向以上说的去访问成员函数,甚至再过分一点((A*)0)->result();这样都可以。你再火一点把那个0换成任意一个地址都可以正确调用到那个函数,因为编译器在静态束定的时候只关心那个指针的类型。当然了,不可这样去访问类的成员变量,因为成员变量是在对象的内存布局里面的。

值得说一点的是,如果你在result函数里面有涉及到类的成员变量的访问,那么这显然就会出错了,因为成员变量需要通过传进来的this指针(其实就可以理解成时p指针)去访问对象的内存的。然而此时p还没有指向一个有效的空间。故而出错。


分享到:
评论

相关推荐

    深入解析C++编程中的静态成员函数

    C++静态成员函数 与数据成员类似,成员函数也可以定义为静态的,在类中声明函数的前面加static就成了静态成员函数。如 static int volume( ); 和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一...

    C++ 类的静态成员深入解析

    在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻...

    实例解析C++中类的成员函数指针

    因此,对于C语言中最容易错用的指针,更是不能放过:C++的指针被分成数据指针,数据成员指针,函数指针,成员函数指针,而且不能随便相互转换。而且这些指针的声明格式都不一样: 数据指针 T * 成员数据指针 T...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会...8.3.2 在类外定义成员函数 8.3.3 inline成员函数 8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会...8.3.2 在类外定义成员函数 8.3.3 inline成员函数 8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...

    C++对象布局及多态实现之动态和强制转换

    从这部分开始我们除了利用内存的信息打印来进行探索外,更多的... 执行如下代码,它包括了对象的普通成员函数调用,类的静态成员函数调用、通过指针调用普通成员函数: C010 obj; PRINT_OBJ_ADR(obj) ob

    中国大学MOOC西工大C++课程PPT

    第1讲 C++语言概述 第2讲 信息的表示与存储 ...第32讲 静态成员和友元 第33讲 类的继承与派生 第34讲 派生类成员的访问 第35讲 派生类的构造和析构函数 第36讲 多重继承 第37讲 多态性 第38讲 虚函数

    Visual C++音频视频处理技术及工程实践(分卷0)

    主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地...

    C++入门到精通

    创建一个类模板特定类型的实例 怎样定义类模板的成员 成员函数 静态成员和嵌套类型 以及怎样用类模板来组织我们的程序 最后以一个扩展的类模板的例子作为结束 面向对象的程序设计和 C++的支持机制是第17 18 19 和...

    EDA/PLD中的C++对象布局及多态实现之动态和强制转换

    从这部分开始我们除了利用内存的信息打印来进行探索外,更多的... 执行如下代码,它包括了对象的普通成员函数调用,类的静态成员函数调用、通过指针调用普通成员函数: C010 obj; PRINT_OBJ_ADR(obj) ob

    Visual C++音频视频处理技术及工程实践(分卷7)

    主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地...

    C/C++笔试题(附答案,华为面试题系列)

    3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用 2.引用与指针有什么区别? 1) 引用必须被初始化,指针不必。 2) 引用初始化以后不...

    C/C++程序员面试指南.杨国祥(带详细书签).pdf

    面试题6:简述类成员函数的重写、重载和隐藏的区别 面试题7:简述多态实现的原理 第10章 数据结构 10.1 链表 面试题1:链表和数组有什么区别 面试题2:寻找单链表中间结点 面试题3:怎样把一个单链表反序 10.2 单...

    Visual C++音频/视频处理技术及工程实践 (分卷1)

    主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地...

    Visual C++音频视频处理技术及工程实践地址

    主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地...

    C语言解析教程(原书第4版)(美) 凯利.pdf

    5.7 函数调用和传值调用 5.8 开发大型程序 5.9 使用断言 5.10 作用域规则 5.10.1 平行和嵌套代码块 5.10.2 以调试为目的使用代码块 5.11 存储类型 5.11.1 auto存储类型 5.11.2 extern存储类型 5.11.3 register存储...

Global site tag (gtag.js) - Google Analytics