类作为C++中最具特色的一个语法工具,为我们的编程带来了许多的便利。我们知道一个类可以保存多个不同的数据类型,那么一个类在内存中的数据分别是如何表现得。他和结构体又有什么异同点。首先我们定义一个最简单得类如下所示
然后我们在main中对其进行赋值查看在内存中得保存状态。
可以看到在内存中,其实类只是按照类中定义得数据按顺序存储我们的数据。而base这个变量则是我们这个类的首地址,和结构体的保存形式是一样的。事实上类和结构体唯一的区别只是结构体中声明的变量和方法是public而类是private。
类中的数据既然有public和private,那他们在内存中的保存形式是否不同。
将上述定义的y设置为私有变量,使用init函数对其进行赋值,对应的反汇编代码如下:
从上可以看出无论是public还是private类型,在内存中并没用什么区别,由此可以知道所谓的公有变量或者私有变量都是编译器的检查罢了。如果我们想访问这些私有变量,只需要算出相应地址就可以,如下。
对应反汇编如下:
最后就通过这种方法顺利输出了private变量,结果如下
每个类都可以定于相应的成员函数,这些函数和普通函数的区别是否有不同。为上述的定义增加一个成员函数如下
接下来在main中调用函数并查看反汇编形式来区别成员函数与普通函数如下
可以看到对于成员函数的调用,唯一的区别就是在调用之前编译器会把类的内存地址赋给ecx。test函数的反汇编如下
从上可以看出,成员函数和我们平时写的普通函数的区别就在于在调用成员函数的时候,编译器首先会把类的地址赋给ecx。而在函数执行的过程中,会首先把这个地址给到局部变量。那么这么做的目的是为何,保存的这个地址有何作用?
根据上面的讲解我们知道类所定义的变量最后在内存中会按顺序保存着,而要找到这些变量的地址,我们首先就需要得到类在内存中的地址。而这个地址就是根据ecx来进行传递。修改上面类的定义如下:
此时我们需要在main中调用InitData来为我们的成员变量赋值。对应的反汇编代码如下
从上面可以看出,我们对InitData调用的时候,首先将两个参数压入栈中,然后把类变量的地址赋给ecx,函数的反汇编如下
从上面可以看出在调用成员函数之前将类变量的地址赋给ecx是为了在成员函数中可以顺利找到类变量的地址,以此来找到相应的数据进行操作。
编写C++程序时候,我们经常需要用到函数重载这个特性,那么函数重载究竟是如何实现,如何做到同名函数不同功能。修改上述类定义如下
在main函数中我们分别调用两个函数,反汇编如下
可以看到对于重载的函数的调用,编译器这里产生的两个call的地址是完全不一样的。在内存中分别查看这两个地址如下
这两个地址分别代表了两个函数的在内存中的位置,所以所谓的函数重载就只是编译器为我们生成了不同的函数而已。
在C/C++中允许我们使用运算符重载技术来简化我们的开发,那么运算符重载是如何实现的,修改类定义如下
以上实现了对++的重载,我们在main函数中查看编译器的实现如下:
由上可以看出,所谓的运算符重载,其实就是编译器为我们实现了一个成员函数,这个成员函数的功能就是我们所写的运算符重载的函数,这样当相应的类实例进行运算时候就会调用相应的函数。我们接着看实现的函数。
可以看到,实现的函数便是我们写的函数,完成的就是类成员变量的自增操作,以上便是类的运算符重载。最后的程序运行结果如下
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-10-20 11:22
被1900编辑
,原因: