核心简记
- 类的基本思想是数据抽象与封装。接口与实现分离。
- 类的编译先编译成员声明再编译函数体
- 函数在概念上属于类但不定义在类的要声明在同一头文件中,实现在同一cpp文件中。
- 构造函数名字与类相同,无返回值。构造函数不能为const,直到构造函数完成初始化过程,对象才有常量属性。
- struct与class唯一的区别是默认访问权限。struct为public
- 使用时c++式与c式的class 类名,等价。
- 类的声明是class 类名,定义前的类是不完整的,可以定义其指针与引用,只有当类完成后才算定义。
- ::表示全局
- 构造函数中对象成员初始化时机:初始化类表、默认初始化。函数体执行前已经是初始化好的了。函数体内是赋值操作
- 构造函数成员的初始化顺序与类定义中顺序一致,与初始值列表无关。
- 构造函数可以提供默认实参,全部参时可以省去默认构造
定义类
|
|
这是类的定义。数据为声明。成员函数的声明必须在类内部,定义可内可外,定义在内部为隐式inline。因为类的定义放在头文件为编译器识别用的接口,而实现在.cpp文件中,.h被每个使用者包含,因此识别出的定义可以用于inline。这与inline应该定义在头文件是一致的。
调用方法时传入对象地址作为this。this为一个常量指针,不可更改this。在成员函数参数列表后加const关键字,可以使指针指向常量。对于初始化时的拷贝,底层忽略const因为初始化为拷贝底层,const对拷贝没有影响,而顶层const的类型是需要符合才可以拷贝的。当this指向常量时,普通对象可用常量成员函数,但常量对象不能使用普通函数。常量对象只能调用常量成员函数。
如果没有定义构造函数将生成默认构造函数,默认构造初始化规则:类内初始值、默认初始化。
可以用=defult;生层默认构造函数,可以写在声明或定义。写在声明为内联。
构造函数参数列表后可以加:构造函数初始值列表。可以为对象成员赋初始值。成员被忽略时将以合成默认构造相同方式初始化。一旦进入构造函数的函数体,成员已经初始化了。
public为整个程序可访问,private是仅类内。
类可以声明友元让其访问私有成员。友元不是类的成员,其仅仅是访问权限的指定,不是一个完整声明,因此该函数必须再声明一次。
类可以有类型成员,通过::在外部使用。
类成员函数inline修饰在声明与定义都可以,但都要在.h内。因为内联要函数定义,需要在一个模块内被编译器识别到。
成员函数可以重载
类的成员用mutable修饰可以成为可变数据,即使在const对象中也可被修改。
类内初始值必须以=或者{}表示。
返回值为this的引用可以在之后连用.。一般的返回为拷贝,会对临时量使用.
一个const的成员函数以引用形式返回this返回的将是常量引用,此时可以定义俩个版本的包装函数封调用非const版本,一个返回为const引用,一个为普通引用。为顶层可区分
友元:
可以声明友元类,不存在传递性。每个类控制自己的友元。注意友元只是影响权限,并不是声明。
类的作用域:类的作用域外数据与成员使用访问运算符访问,类型成员使用作用域运算符。函数定义时,一旦遇到类名,定义的剩余部分就在类的作用域之内了,但返回类型在函数名前,所以返回类型要加作用域。
编译时类定义顺序:先编译成员声明、再编译函数体。注意只是函数体,声明中的名字要之前可见。同时类型名要特殊,内外不可同名。
成员定义的名字查找方式:函数体内使用前、类内、函数定义前。函数定义前不仅是类定义前,还有函数定义前也算。
委托构造:
初始列表只有其它构造函数,传入参即可。受委托的构造函数初始值列表和函数体依次被执行,之后再执行委托者的函数体。
使用默认构造时:
默认构造不加()。
隐式类型转化:
如果有构造只接受一个参数,就定义了一个隐式转化机制。其只允许一步转化。在赋值或参数传递时都可发生使用。使用explicit声明构造函数时阻止作为转化。
拷贝初始化与直接初始化是不同的,拷贝初始化会执行转化过程,直接初始化为直接使用构造。
聚合类:
聚合类所有成员public、没有构造、没有类内初始值等。作为数据集合。可以使用列表初始化它。
静态成员:
可以是函数、数据。使用作用域运算符直接访问,也可对象使用访问运算符。
定义静态成员函数时,声明加static,定义不加。数据类型必须定义初始化在外部。由于数据类内只是声明,因此定义在外部,同时static也只加在声明。
反汇编
.h:
.cpp
x86-64
指令简记
分析
main:
sub_7B90
sub_7C10
sub_7C90 sub_7A70
ARM-64
指令简记
分析
|
|
析构:
构造与函数调用都要传对象地址作为this
默认析构是对每个成员析构
debug下并没有隐式内联…依然全部化为了函数调用。核心为找到this,确定数据结构