C++之类的一些特性(反汇编)
一、结构体与类
C++中,结构体和类都具有构造函数、析构函数和成员函数。
区别:结构体的访问控制默认为public,而类的默认访问控制是private。
特点:对于C++中的结构体而言,public、private、protected的访问控制都是在编译器进行检查,当越权访问时,编译过程中会检查出此类错误并给予提示。编译成功后,程序在执行的过程中不会在访问控制方面做任何检查和限制。
因此,反汇编中,C++中的结构体与类没有分别,两者的原理相同,只是类型名称不同。
二、对象的内存布局
类的实例化对象都存放在堆中!!!!(可以通过反汇编实例化代码,可知实例的首地址一般都在堆中)
对象的大小只包含数据成员,类成员函数属于执行代码,不属于类象的数据。
#include<iostream>
class CNumber
{
public:
CNumber()
{
m_nOne = 1;
m_nTwo = 2;
}
private:
int m_nOne;
int m_nTwo;
};
int main()
{
CNumber Number;
printf("The adress of class CNumbe : %d \n",&Number); // 这里应该为%X,所以结果显示不同
printf("The size of class CNumbe : %d \n",sizeof(CNumber));
printf("The size of class CNumbe : %d \n",sizeof(Number));
return 0;
}
对象在内存中至存放数据成员。
提示:为什么类中不能定义自身的对象?
#include<iostream>
class CNumber
{
public:
CNumber()
{
m_nOne = 1;
m_nTwo = 2;
}
CNumber Num; // 这里是对自身对象的实例化......
private:
int m_nOne;
int m_nTwo;
};
int main()
{
CNumber Number;
printf("The adress of class CNumbe : %d \n",&Number);
printf("The size of class CNumbe : %d \n",sizeof(CNumber));
printf("The size of class CNumbe : %d \n",sizeof(Number));
return 0;
}
编译提示:
解释:因为类需要在申请内存的过程中计算出自身的实际大小,以用于实例化。如果在类中定义了自身的对象,在计算各数据成员的长度时,又会回到自身,这样就形成了递归定义,而这个递归并没有出口,是一个无限的循环递归定义,所以不能定义自身对象作为类成员。
但是可以定义自身类型的指针,因为任何类型的指针在内存中都是32位,4个字节,等同一个常量值。
例:
将上面代码中 CNumber num;修改为 CNumber *num;
结果如下:
注意:这里实例化后的Number对象,有三个数据成员,一个指向了有3个变量的结构的指针,两个变量.
1、空类
#include<iostream> class CNumber { }; int main() { CNumber Number; printf("The adress of class CNumbe : %X \n",&Number); printf("The size of class CNumbe : %d \n",sizeof(CNumber)); printf("The size of class CNumbe : %d \n",sizeof(Number)); return 0; }
结果:
debug版反汇编:
10: CNumber Number; // 这句直接不会编译 11: printf("The adress of class CNumbe : %X \n",&Number); 00401048 lea eax,[ebp-4] // 有地址 0040104B push eax 0040104C push offset string "The adress of class CNumbe : %X "... (00431044) 00401051 call printf (00408170) 00401056 add esp,8 12: printf("The size of class CNumbe : %d \n",sizeof(CNumber)); 00401059 push 1 // 只分配一个字节 0040105B push offset string "The size of class CNumbe : %d \n" (0043101c) 00401060 call printf (00408170) 00401065 add esp,8 13: printf("The size of class CNumbe : %d \n",sizeof(Number)); 00401068 push 1 0040106A push offset string "The size of class CNumbe : %d \n" (0043101c) 0040106F call printf (00408170) 00401074 add esp,8
Release版本基本相同