类
class
1. 概念
一组具有相同属性和行为的对象的集合,体现了面向对象的抽象和封装的两个特点
2. 语法:
typedef class _MyClass_{
};
3. C++四大特性
- 抽象:数据抽象,过程抽象,只关注目标有什么特点,不在意具体实现
- 封装:即隐藏对象的属性和实现细节,仅对外公开接口
- 继承:子类继承父类的属性和行为
- 多态:不同的对象接受同一消息而产生不同的行为 (不同对象使用同一成员函数产生不同结果)
4. 三种访问属性
public,protected,private
5. 构造和析构
构造函数:必须在public里,且与类名相同,无返回值
析构函数:前面加~,必须在public里,且与类名相同,无返回值
6. 成员函数定义
需要用 :: 表示作用域
7. 成员函数重载
函数名字一样,函数的参数个数不同或函数的参数类型不同(返回值不同不行)
8. 类成员函数调用约定
thiscall(c++):是c++成员函数特有的调用方式,不属于关键字,无法显式声明为thiscall调用方式
-
为什么面向对象可以用共同的方法来处理不同的数据?
(这个问题可以用调用约定:fastcall=c++中的thiscall)
-
调用成员函数时,首先将对象地址赋给ecx,再call函数(ecx放当前对象地址) (函数在代码段code,成员变量在栈区)
在成员函数开栈之后,在压入基本的ebx,esi,edi之后会push ecx,即把v1变量地址压入
-
(为什么会有这一步,即push ecx,因为后面要用到edi,eax,ecx三个寄存器来初始化,ecx中保存的数据会被覆盖掉,所以需要push把ecx中的值存进去)
最后有一步:pop,ecx;即把之前存的数据又放回ecx中,其他还原;在函数执行前,把ecx中的数据放入this内存中
9. 类指针
this指针:保存的当前的对象地址(ecx) (传入不同对象地址,同样的方法产生不同效果)
调用成员函数时,编译器利用寄存器ecx保存了对象的首地址,并以寄存器传参的方式将其传递到成员函数中,即this指针(thiscall)
thiscall成员函数要点:
lea ecx, [mem] ; 取对象首地址并存入ecx,要注意观察内存
call FUN_ADDRESS ; 调用成员函数
; 在函数调用内,ecx 尚未重新赋值之前
mov XXX, ecx ; 发现函数内使用ecx中的数据,说明函数调用前对ecx的赋值实际是在传递参数
; 其后 ecx 中的内容会传递给其他寄存器
mov [reg+i], XXX ; 寄存器相对间接寻址方式,如果能排除数组访问,reg中保存的是结构体或者类对象的首地址
使用指针访问结构体或类成员的公式:
type *p;
p->member的地址=指针p的地址值+ member在type中的偏移量
求结构体成员的偏移量:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
10. 访问私有成员
10.1 指针
对于私有成员:虽然语法上进行了封装,但实际使用中,可以通过指针来破解
int *v10=(int*)&v1;
_tprint(_T("%d\r\n"),*v10);
_tprint(_T("%s\r\n"),(TCHAR*)(v10+1));
一样可以取出来
void _MyClass_::ShowName(const TCHAR* name)
{
memcpy(Name, name, (_tcslen(name)+1)*sizeof(TCHAR));
}
10.2 汇编
11. .cpp的结构体
对于c++.cpp文件,结构体和类差不多一样,也有this指针
(但是结构体默认属性public,类private)
12. 类的组成
12.1 成员变量和成员函数
对象中先定义的数据成员在低地址处,后定义的数据成员在高地址处,依次排列,对象大小只包含数据成员,类成员函数属于执行代码,不属于类对象数据
12.2 类中不能定义自身对象
类需要在申请内存的过程中计算出自身的实际大小,以用于实例化;
如果在类中定义了自身的对象,在计算各数据成员的长度时,又会回到自身,这样就形成了递归定义,而这个递归并没有出口,是一个无限的循环递归;
但是,自身类型的指针除外,任何类型的指针在32位下所占用的内存大小始终为4字节,等同于一个常量值,因此将其作为类的数据成员不会影响长度的计算
12.3 对象长度
对象长度的计算公式:对象长度=sizeof(数据成员1)+sizeof(数据成员2)+...+sizeof(数据成员n)
四种特殊情况下该公式不符合:
-
空类
空类中没有任何成员,按照公式计算出来是0字节,类型长度为0,空类就无法取得实例对象的地址,this指针失效,不能实例化;
类中有成员函数,但没有成员变量,需要实例化,分配1字节的空间用于类的实例化(实际上这1字节的数据并没有被使用)
-
内存对齐
-
静态数据成员
静态数据成员虽然在类中被定义,但存放位置与全局变量一致 -
类中有虚函数
对象中有隐含成员虚表指针(32位4字节,64位8字节)
13. 静态数据成员
程序运行前,静态数据成员就已经存在,而此时类还没有实例对象,访问时无需this指针,静态数据成员为对象共有
14. 结构体和类的异同
相同点:都具有构造函数、析构函数和成员函数,
区别:结构体的访问控制默认为public,而类的默认访问控制是private
本文作者:修竹Kirakira
本文链接:https://www.cnblogs.com/XiuzhuKirakira/p/17090779.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步