C++对象模型和this指针
4.3.1 成员变量和成员函数分开存储
在C++中,类内的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上
空类(类里面是空的),空对象占用内存空间为:1字节。
静态成员变量,类内声明,类外初始化。
4.3.2 this指针概念
this指针指向被调用的成员函数所属的对象。
4.3.3 空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
4.3.4 const修饰成员函数
常函数:
- 成员函数后加const后我们称为这个函数是常函数
- 常函数内不可以修改成员属性
- 成员属性声明时加关键字mutable后,在常函数中依然可以修改
//常函数
void func() const
{
cout << "常函数" << endl;
}
常对象:
- 声明对象前加const称该对象为常对象
- 常对象只能调用常函数
this指针的本质 是指针常量 指针的指向是不可以修改的。
常对象不可以调用普通成员函数,因为普通成员函数可以修改属性。
4.4 友元
友元的目的就是让一个函数或者类 访问另一个类中私有成员
友元的关键字为friend
友元的三种实现
- 全局函数做友元
- 类做友元
- 成员函数做友元
4.5 运算符重载
4.5.1 赋值运算符重载
C++编译器至少各一个类添加4个函数
- 默认构造函数(无参,函数体为空)
- 默认析构函数(无参,函数体为空)
- 默认拷贝构造函数,对属性进行值拷贝
- 赋值运算符operator=,对属性进行值拷贝
类名后面跟一个小括号,称之为匿名对象,执行完后立即释放。
如:
Person() 其中Person是类名
4.6 继承
继承的好处,减少重复代码
继承方式:
父类中所有非静态成员属性都会被子类继承下去。
父类中私有成员属性,是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了。
继承中的构造和析构顺序如下:
先构造父类,再构造子类,析构的顺序与构造的顺序相反。
4.6.1 继承中的同名静态成员处理
4.7 多态
4.7.1 多态的基本概念
多态分为两类
- 静态多态:函数重载 和 运算符重载属于 静态多态,复用函数名
- 动态多态:派生类和虚函数实现运行时多态
静态多态和动态多态区别:
- 静态多态的函数地址早绑定 - 编译阶段确定函数地址
- 动态多态的函数地址晚绑定 - 运行阶段确定函数地址
动态多态满足条件
- 有继承关系
- 子类重写父类的虚函数
动态多态使用:父类的指针或引用 指向 子类对象。
重写:函数返回值类型 函数名 参数列表 完全一致,只有函数体中的内容不同 称为函数重写。
4.7.2 多态的原理剖析
要想写多态,父类中需要写虚函数,子类需要对父类中的虚函数进行重写。
4.7.3 纯虚函数和抽象类
纯虚函数语法:virtual 返回值类型 函数名(参数列表) = 0;
当类中有了纯虚函数,这个类也称为抽象类。
抽象类特点:
- 无法实例化对象
- 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
多态:一个接口有多种形态,由于你传入的对象不一样,但是都是同一个接口,去实现不同的功能。
4.7.4 虚析构和纯虚析构
在多态使用时,父类指针或引用指向子类对象,如果子类中有属性开辟到堆区,父类指针在delete的时候,父类指针无法释放子类中的析构代码。
父类指针在析构时候 不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄漏。
解决方式:将父类中的析构函数改为虚析构或者纯虚析构。
1.父类中如果有纯虚函数,子类必须对父类中的纯虚函数进行函数重写,否则子类是抽象类,无法实例化;
2.父类中有纯虚析构,需要函数声明也需要函数实现,在类外部进行函数实现;
3.有了纯虚析构之后,这个类也属于抽象类,无法实例化对象。
5 文件操作
程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放。
通过文件可以将数据持久化
C++中对文件操作需要包含头文件<fstream>
文件类型分为两种:
- 文本文件:文件以文本的ASCII码形式存储在计算机中
- 二进制文件:文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们
操作文件的三大类:
- ofstream:写操作
- ifstream:读操作
- fstream:读写操作
5.1 文本文件
5.2 二进制文件