第50课 C++对象模型分析(上)
1. 回归本质
(1)class是一种特殊的结构体(struct)
①在内存中class依旧可以看作变量的集合
②class与struct遵循相同的内存对齐规则
③class中的成员函数与成员变量是分开存放的。即每个对象有独立的成员变量,所有对象共享类中的成员函数。
(2)值得思考的问题:两者相等
【编程实验】C++对象内存布局初探 50-1.cpp
#include <iostream> #include <string> using namespace std; class A { //默认访问权限为private int i; int j; char c; double d; public: void print() { cout << "i = " << i << ", " << "j = " << j << ", " << "c = " << c << ", " << "d = " << d << endl; } }; struct B { //默认访问权限为public int i; int j; char c; double d; }; int main() { A a; //class和struct在内存布局上是一样的。大小相同 cout << "sizeof(A) = " << sizeof(A) << endl; //20 bytes cout << "sizeof(a) = " << sizeof(a) << endl; //20 bytes cout << "sizeof(B) = " << sizeof(B) << endl; //20 bytes cout << endl;
a.print(); cout << endl; B* p = reinterpret_cast<B*>(&a); //将类强制转化结构体 //利用结构体对类的private成员进行赋值(注意是private成员) //说明class在运行时,private访问权限只在编译期起作用。
p->i = 100; p->j = 200; p->c = 'C'; p->d = 3.14; a.print(); //class中的private成员被改变 return 0; }
/*输出结果
sizeof(A) = 20
sizeof(a) = 20
sizeof(B) = 20
i = 4202544, j = 65535, c = , d = 8.69169e-311
i = 100, j = 200, c = C, d = 3.14
*/
(2)运行时的对象退化为结构体的形式(类的成员变量的内存布局)
①所有成员变量在内存中依次排布
②成员变量间可能存在内存空隙
③可以通过内存地址直接访问成员变量
④访问权限关键字在运行时失效
2. C++对象模型(类的成员函数的内存布局)
(1)类中的成员函数位于代码段中
(2)调用成员函数时对象地址作为参数隐式传递
(3)成员函数通过对象地址访问成员变量
(4)C++语法规则隐藏了对象地址的传递过程
【编程实验】对象本质分析(用C写面向对象)
//C++示例 50-2.cpp
#include <iostream> #include <string> using namespace std; class Demo { int mi; int mj; public: Demo(int i, int j) { mi = i; mj = j; } int getI() { return mi; } int getJ() { return mj; } int add(int value) { return mi + mj + value; } }; int main() { Demo d(1, 2); cout << "sizeof(d) = " << sizeof(d) << endl; //8 cout << "d.getI() = " << d.getI() << endl; //1 cout << "d.getJ() = " << d.getJ() << endl; //2 cout << "d.add(3) = " << d.add(3) << endl; //6 return 0; }
//C语言模拟面向对象
//50-2.h
#ifndef _50_2_H_ #define _50_2_H_ typedef void Demo; //声明成员函数(接口) Demo* Demo_Create(int i, int j); int Demo_GetI(Demo* pThis); int Demo_GetJ(Demo* pThis); int Demo_Add(Demo* pThis, int value); void Demo_Free(Demo* pThis); #endif
//50-2.c
#include "50-2.h" #include <malloc.h> //利用C语言来实现面向对象 //定义结构体 struct ClassDemo { int mi; int mj; }; //实现各成员函数(带this指针)
//构造函数 Demo* Demo_Create(int i, int j) { struct ClassDemo* ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo)); if(ret != 0) { ret ->mi = i; ret ->mj = j; } return ret; } int Demo_GetI(Demo* pThis) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->mi; } int Demo_GetJ(Demo* pThis) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->mj; } int Demo_Add(Demo* pThis, int value) { struct ClassDemo* obj = (struct ClassDemo*)pThis; return obj->mi + obj->mj + value; } //析构函数 void Demo_Free(Demo* pThis) { free(pThis); }
//main.c
#include <stdio.h> #include "50-2.h" int main(void) {
Demo* d = Demo_Create(1, 2); //Demo* d = new Demo(1, 2); //各函数调用中,传入this指针:d printf("d.mi = %d\n", Demo_GetI(d)); //d->getI(); printf("d.mj = %d\n", Demo_GetJ(d)); //d->getJ(); printf("Add(3) = %d\n", Demo_Add(d, 3)); //d->add(3); //d->mi = 100; //相当于私有变量,不能直接通过this指针(d)来访问 Demo_Free(d); return 0; }
3. 小结
(1)C++中的类对象在内存布局上与结构体相同
(2)成员变量和成员函数在内存中分开存放
(3)类中的成员变量跟struct遵循相同的内存对齐规则
(4)类中的成员函数位于代码段中
(5)访问权限关键字在运行时失效
(6)调用成员函数时对象地址作为参数隐式传递