隐藏的默认构造函数
- 没有参数的构造函数称为【默认构造函数】
- 如果没有手动定义构造函数,编译器会给你一个【“隐藏的默认构造函数”】
- 如果数据成员使用了【类内初始值】,那么这个数据成员使用这个初始值初始化
- 否则,采用默认初始化(不做任何动作)
- 只要手动的定义了任何一个构造函数(不论是有参还是无参),编译器都不会再给你“隐藏的默认构造函数”
隐藏的赋值函数(运算符重载:operator=)
- 如果没有手动定义赋值函数,编译器会给你一个,给你的这个只会简单的进行位拷贝
隐藏的析构函数
- 如果没有手动定义析构函数,编译器会给你一个,给你的这个什么动作都不做
调用拷贝构造函数的时机
- Person p2(p1); //创建对象时调用拷贝构造函数
- Person p2 = p1; //创建对象是调用拷贝赋值函数
注意: Person p2 = p1; //这样编译器会将其变成 Person p2(p1); Person p3; p3 = p1; //这样会调用赋值函数(operator=)
- 函数的形参是对象且不是引用类型
- 函数的返回值是对象且不是引用类型
- 对象数组的初始化列表使用对象
const数据成员
- const数据成员的初始化方式
- 使用【类内初始值】(c++11)
- 使用构造函数初始化列表
注意:如果同时使用这两种,以初始化列表中的值为准
注意:不能在构造函数和任何其他成员函数中,对const成员赋值
类的静态数据成员的初始化
- const静态数据成员,可以用【类内初始值】初始化,也可以在类外初始化
- 非const静态数据成员,只能在类外初始化
const成员函数
- 不能对数据成员做修改
- const对象只能调用const成员函数
面向对象编程:composition and delegation
- composition: 同生共死关系
被拥有的对象的生命周期和其拥有者的生命周期一致。
使用方式:- 类内直接包含其他类
- 类内包含其他类(被组合对象)的指针,在创建类的对象时要同时创建被组合的对象,类的对象被销毁时要同时销毁被组合的对象
- delegation:借用关系,拥有者不需要对被拥有者的生命周期负责。
使用方式:类内包含其他类的指针
继承
- 子类可以重定义父类继承下来的方法。
- 不管什么继承方式,父类的public和protected的成员都可以被子类直接访问
- 继承方式影响的访问权限只是对外部而言。子类对父类的成员的访问权限只需要看父类成员是public,protected还是private,不用看子类是怎么继承过来的
-
继承中的构造函数
- 调用方式
- 显式调用
- 隐式调用(编译器帮你调用父类的默认构造函数)
- 调用顺序
- 静态数据成员(这个感觉应该不用放在这,放在这仅作提醒)
- 父类构造函数
- 非静态数据成员
- 本类的构造函数
- 调用方式
-
继承中的析构函数
- 构造函数的调用顺序反过来就是了
子类对象传给父类
class A {
void func() {}
};
class B : public A {
void func() {}
};
void run(A a) {
a.func();
}
main() {
B b;
// 实参是B类对象,形参是A类对象,等价于传进去的是A类对象
//(这不就是将B类对象中属于A类的那部分传过去了,就像把8字节整型传给四字节整型会截断一样)
run(b);
}
多态
- 虚函数
- 父类的成员函数加了virtual,则其子类自动继承为虚函数,子类可以不加virtual,不过建议加上
- 三必要素
- 子类重定义父类虚函数
- 父类指针(引用)指向子类对象
析构函数与多态
- 对父类的虚函数声明为虚函数时,析构函数具有多态效应。
具体是指,如果父类指针指向的是子类对象,当使用delete释放该指针所指空间时,此时如果父类析构函数不是虚函数,只会按照父类的析构函数顺序调用。但其实我们希望的是按照指针具体所指的子类,按照它的析构函数的调用顺序调用,所以可能会出现问题。那么,最好任何时候(只要该类有可能派生其他类)都在父类析构函数加上virtual。
赋值运算符的重载
- 参数必须是引用类型或者值类型,不能是指针类型,编译器不认指针类型的赋值运算符重载
纯虚函数和抽象类
- 具有纯虚函数的类就是抽象类
- 一个类继承了一个抽象类,则
- 实现所有的纯虚函数,那么这个类就不再是抽象类
- 实现部分纯虚函数或者一个都不实现,那么这个类还是抽象类
- 抽象类不能创建对象
冷知识
- 重载类型转换:类类型->基本类型
- 方式:重载类型转换符,
operator 基本类型名() {}
- 例如:
operator int(){}
, 注意不能有返回值
- 方式:重载类型转换符,
- final关键字
- 修饰类:则该类不能被继承
- 修饰类的虚函数:则该函数不能再子类被重定义
- override关键字
- 仅能用于虚函数,提示该函数是在重定义父类的虚函数
- 只需在声明时写上,不需在实现时写上
- 模板类的静态数据成员
- 不同的实例化的模板类各自有各自的静态数据成员