C++ 对象模型分析(上)
回归本质
class是一种特殊的struct
- 在内存中 class 依旧可以看作变量的集合
- class 与 struct 遵循相同的内存对齐规则
-
class 中的成员函数与成员变量是分开存放的
- 每个对象有独立的成员变量
- 所有对象共享类中的成员函数
成员函数也是函数,只要时函数,编译之后就是放在代码段中的
值得思考的问题
class A
{
int i;
int j;
char c;
double d;
};
sizeof(A) = ?
class B
{
int i;
int j;
char c;
double d;
};
sizeof(B) = ?
对象内存布局初探
#include <iostream>
#include <string>
#include <math.h>
#include <stdio.h>
using namespace std;
#pragma pack(4)
class A
{
int a;
int b;
char c;
double d;
public:
void print()
{
cout << "a =" << a << ", "
<< "b =" << b << ", "
<< "c =" << c << ", "
<< "d =" << d << endl;
}
};
#pragma pack()
#pragma pack(4)
struct B
{
int a;
int b;
char c;
double d;
};
#pragma pack()
int main()
{
A a;
struct B b;
printf("sizeof(A) = %lu\n", sizeof(a));
printf("sizeof(struc B) = %lu\n", sizeof(struct B));
a.print();
struct B *p = reinterpret_cast<struct B* > (&a);
p->a = 10;
p->b = 20;
p->c = 'a';
p->d = 1.011;
a.print();
return 0;
}
对象就是一个特殊的结构体。可以重新解释对象内存,指针修改对象内部的私有成员 struct B *p = reinterpret_cast<struct B* > (&a)
运行时的对象退化为结构体形式
- 所有程序变量在内存中依次排布
- 成员变量间可能存在内存空隙
- 可以通过内存地址直接访问成员变量
- 访问权限关键字(private),在编译的时候有效,在运行的时候就失效了
问题1
如何调用一个成员函数?
答:
点 操作符。编译器在背后做了一个操作,将一个地址(这个地址就是对象的地址)传递到成员函数内部。
问题2
成员变量和成员函数时在内存中分开存放的,为啥成员函数就可以访问成员变量?
答:
this指针。this 指针只能在成员函数内部使用,代表当前对象,保存了当前对象的地址
- 类中成员函数位于代码段中
- 调用成员函数时**对象地址作为参数隐式传递
- 成员函数通过对象地址访问成员变量
- C++ 语法规则隐藏了对象地址传递过程
编程实验:对象本质分析
// 50—2.h
#ifndef __50_2_H__
#define __50_2_H__
typedef void Demo;
Demo *DemoCreate(int i, int j);
int GetI(Demo *pthis);
int GetJ(Demo *pthis);
int AddValue(Demo *pthis, int value);
void DemoFree(Demo *pthis);
#endif
// 50-2.c
#include <stdio.h>
#include <stdlib.h>
#include "50-2.h"
struct ClassDemo
{
int mi;
int mj;
};
Demo *DemoCreate(int i, int j)
{
struct ClassDemo *ret = (struct ClassDemo*)malloc(sizeof(struct ClassDemo));
if(ret != NULL)
{
ret->mi = i;
ret->mj = j;
}
return ret;
}
int GetI(Demo *pthis)
{
if(pthis != NULL)
{
return ((struct ClassDemo*)pthis)->mi;
}
}
int GetJ(Demo *pthis)
{
if(pthis != NULL)
{
return ((struct ClassDemo*)pthis)->mj;
}
}
int AddValue(Demo *pthis, int value)
{
if(pthis != NULL)
{
return ((struct ClassDemo*)pthis)->mj + ((struct ClassDemo*)pthis)->mi + value;
}
}
void DemoFree(Demo *pthis)
{
free (pthis);
}
// test.c
#include <stdio.h>
#include "50-2.h"
int main()
{
Demo *d = DemoCreate(1, 2);
printf("%d\n", GetI(d));
printf("%d\n", GetJ(d));
printf("%d\n", AddValue(d, 10));
DemoFree(d);
}
输出
1
2
13
小结
- C++ 中的类对象在内存布局上与结构体相同
- 成员变量和成员函数在内存中分开存放
- 访问权限关键字在运行时失效
- 调用成员函数时对象地址作为参数隐式传递
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。