C++对象模型,其实就是C++中的对象在内存中是如何排布的。
C++中的对象包含了成员变量和成员函数,其实就是研究C++中的类对象它的成员变量和成员函数在内存中是如何排布的。
回归本质
class 是一种特殊的struct(之所以特殊,是因为它们的默认访问级别不一样)
-在内存中class依旧可以看作变量的集合
-class与struct遵循相同的内存对齐规则
-class中的成员函数与成员变量是分开存放的
每个对象有独立的成员变量 (存在的位置可能是栈空间、堆空间、全局数据区)
所有对象共享类中的成员函数(只可能存放在代码段)
实验一:
#include<iostream>
#include <string>
using namespace std;
class A
{
int i;
int j;
char c;
double d;
};
struct B
{
int i;
int j;
char c;
double d;
};
int main()
{
cout << "sizeof(A)=" << sizeof(A) << endl; //20bytes
cout << "sizeof(B)=" << sizeof(B) << endl; //20bytes
return 0;
}
实验二:
在class A中,给它加上一个成员函数print,此时再看类A所占的内存大小。
class A
{
int i;
int j;
char c;
double d;
public:
void print()
{
cout << "i=" << i << ","
<< "j=" << j << ","
<< "c=" << c << ","
<< "d=" << d << "," << endl;
}
};
打印结果还是20个bytes,说明了:
一个C++对象代表的仅仅是成员变量的集合,
实验三:
#include<iostream>
#include <string>
using namespace std;
class A
{
int i;
int j;
char c;
double d;
public:
void print()
{
cout << "i=" << i << ","
<< "j=" << j << ","
<< "c=" << c << ","
<< "d=" << d << "," << endl;
}
};
struct B
{
int i;
int j;
char c;
double d;
};
int main()
{
A a;
cout << "sizeof(A)=" << sizeof(A) << endl;
cout << "sizeof(a)=" << sizeof(a) << endl;
cout << "sizeof(B)=" << sizeof(B) << endl;
a.print();
// B* p = &a; 因为B和a的类型不同,需要进行强制类型转换。使用reinterpret_cast关键字,为什么使用这个关键字呢?
//需要重新解释a对象所代表的这段内存。
B* p = reinterpret_cast<B*>(&a);
//此时将a对象当成一个结构体B的变量来使用
p->i = 1;
p->j = 2;
p->c = 'C';
p->d = 3;
a.print();
return 0;
}
该实验说明,一个对象本质上就是一个特殊的结构体变量
运行时的对象退化为结构体的形式
-所有成员变量在内存中依次排布
-成员变量间可能存在内存空隙
-可以通过内存地址直接访问成员变量
-访问权限关键字在运行时失效
比如说private成员不能在类的外部被访问,这一点仅仅是在编译的时候有效,也就是说在写完代码之后,编译器在进行语法检查的时候访问权限关键字会起作用,但是一旦编译通过,C++面向对象程序将变成二进制可执行程序,在这个时候就没有访问权限关键字的概念了。可以使用指针,使用内存地址直接修改成员变量的值。通过上述实验三,就可以做到。