运算符重载
运算符重载,就是对已有的运算符进行重定义,赋予其另一种功能, 以适应不同的类型
加号运算符重载
如果想让自定义数据 进行+ 号运算, 那么就需要重载+号运算符
在成员函数里面或者全局函数里 重写一个+运算符的函数
函数名operator+(){}
运算符重载也可以提供多个版本
重载左移运算符
- 不要随意卵用符号重载
- 内置数据类型的运算符不可以重载
- cout<<直接对Person 自定义数据类型 进行输出
- 写到全局函数中
ostream & operator<<(ostream &cout,Person &p1) //第一个参数cout,第二个参数Person
{
cout << "m_A = " << p1.m_A << " M_b = " << p1.m_B;
return cout;
}
- 如果访问的时候要访问p1的私有 成员, 那么全局函数要做友元函数
前置 后置 ++ 运算符重载
1. 自己实现int类型 MyInterger
- 内部维护以int数据
- MyInterger myInt
- myInt++ 后置 ++myInt operator++()前置 operator(int) 后置
- 前置理念, 先++, 后返回自身,, 后置理念, 先保存原有值 内部++,再返回临时数据
智能指针实现
Person 类有 showAge 成员函数
如果 new出来的Person对象就要让程序员自觉的去释放 delete
如果有了智能指针,让智能指针托管这个person对象,对象的释放就不用吵醒了,让智能指针管理
为了让智能指针像普通的Person* 指针一样使用,就要重载-> 和*
赋值运算符重载
- 系统默认给类提供, 赋值运算符写法 是简单值拷贝
- 导致如果类中有指向堆区的指针, 就可能出现深拷贝浅拷贝问题
- 所以要重载=运算符
- 如果系统用链式编程 return *this
[]运算符重载
- 返回数组索引的引用
- int & operator[](int index)
- return this->pAddress[index]
关系运算符重载
- 自定义数据类型 不会内部做比较 == !=
- 所以要重载!= ==
函数调用重载
- () 仿函数 对象()看似像函数调用
- MyAdd() 匿名对象
- 不要重载 &&和||
强化训练 - 字符串封装
- cout 输入自定义的字符串
- cin 让用户输入字符串内容
- 重载 = 运算符
- 重载+ 运算符
- 重载[]运算符
- 重载==运算符
继承和派生
- 网页有很多 公共部分
- 导致实现有很多重复的代码
- 引出集成, 基类 公共网页
- 具体子类不同的内容方式
- 语法 class 子类 :Public 父类
继承方式
基类中的私有属性不可以被继承
继承中的对象模型
子类会继承父类中所有内容, 包括私有属性
只是我们访问不到, 被编译器所隐藏
继承中的析构和构造函数
- 子类创建对象时, 先调用父类的构造, 然后调用自身的构造
- 析构函数与构造函数顺序相反
- 子类是不会继承父类的构造函数和析构函数
- 补充内推, 如果父类没有合适的默认构造, 那么子类可以采用初始化的方式显示调用父类的其他构造
继承中的同名处理
- 成员属性 直接调用子类, 如果想调用父类, 需要作用域
- 成员函数 直接调用子类, 父类的所有版本都会被隐藏, 除非显示用作用域运算符去调用
继承中静态成员的处理
- 类似非静态成员函数处理
- 如果想访问父类中的成员,加作用域即可
多继承
多继承容易引发二义性问题
class A:public B,public C2 …
如果想解决需要作用域
菱形问题以及解决
解决问题利用虚基类
sheepTUo内部类
- vbptr 虚基类指针
- 指向一张 虚基类标
- 通过表找到偏移量
- 找到共用数据
内部工作原理(可以不掌握)
多态
多态是面向对象程序设计中数据抽象和继承之外的第三个基本特征
静态连编和动态编译
- 多态分类
1.1. 静态多态 函数重载
1.2. 动态多态 虚函数, 继承关系 - 静态连编
地址早绑定, 编译阶段绑定好地址
地址晚绑定,再运行时候再绑定 - 多态
- 父类的引用或指针指向子类对象 虚函数表指针
- 虚函数表, &对象的函数地址,将vfptr继承下来, 指向自己,覆盖掉,子类重写虚函数,重写返回值,,参数,类型都一致。
多态原理解析
当 父类中有了虚函数之后, 内部结构发生了变换
内部多了一个vfprt
virtual function pointer 虚函数表指针
指向vftable 虚函数表
父类结构 vfpter
子类中继承会继承虚函数表指针, 以及虚函数表
如果发生了重写,会替换掉虚函数表中原有的函数地址
,改为自己实现的方法。
深入剖析, 内部如何实现调用
(void(*)()) (*(int*)*(int*)animal())