运算符重载:
让类的对象支持操作符运算
1.单目
#O
O.operator#()
or operator#(O)
~ ! - ++ -- 用哑元来区分前后++--
2.双目
M#N
M.operator#(N)
or operator#(M,N)
= + - * / % && || & | ^ [] -> < <= > >= == !=
[] 一般来说提供常版本和非常版本
排序、查找 一般来说都是重载 <
== != 一般都是成对实现的
find(v.begin(),v.end(),key); < a<b||b<a == false a==b
3.三目
?:
4.杂项
new new[] delete delete[] 全局函数 静态成员函数
() 如果一个类重载了() 那么该类的对象称为函数对象
一元谓词 重载() 提供一个参数 list.remove_if()
sort() 二元谓词
友元类 友元函数:
在一个类里面可以用friend关键字来声明友元类和友元函数,
M#N M不是当前类类型成员,只能以友元函数的方式重载 cout<< cin>>
1.不是所有运算符都能够重载
. :: .* ?: sizeof typeid
2.不是所有的运算符都能够以友元方式重载(只能以成员方式重载)
= [] () ->
3.只能友元方式重载
<< >>
4.不能创建新的运算符
x**y
5.重载的运算符一般要保持运算符本身的含义及运算规则
java简化了C++,把C++复杂的语句全部删除 指针 全部是引用(除了基本数据类型) 没有运算符重载
显式转换 多继承
继承:
用一个类去继承另外一个类 被继承的类称为父类 基类 继承父类的类称为子类 派生类
子类继承父类 子类拥有父类的属性和方法
继承是为什么 代码的复用 和 功能的扩展
语法规则:
class S: 继承方式1 F1,继承方式2 F2,...{
}
继承方式:
public 公有继承
protected 保护继承
private 私有继承
访问控制属性 本类 子类 其它地方
public OK OK OK
protected OK OK NO
private OK NO NO
继承方式改变从父类中继承下来的成员属性在子类中的访问控制属性:
继承方式 公有属性 受保护属性 私有属性
public 公有 受保护 X
protected 受保护的 受保护 X
private 私有属性 私有属性 X
保护继承和私有继承的意义: 在于不会让父类公开的属性和方法通过子类扩散出去
子类的构造函数:
默认的无参构造函数:
1.按照继承顺序依次调用父类的构造函数(默认是无参构造)
2.按照声明顺序依次调用类类型成员的构造函数(默认是无参构造)
3.执行本类的构造函数体
如果一个类继承的父类没有无参构造函数,那么这个子类你一定要实现构造函数
(不能使用默认提供的)
如果父类没有无参构造,那么子类必须在所有的构造函数的初始化列表中显示调用父类的有参构造
子类名(形参列表):父类名(实参列表),...{}
子类的析构函数:
默认的析构函数会调用父类的析构函数
析构函数的调用顺序 和 构造函数调用顺序 正好相反
手动实现的子类析构函数 依然 会调用父类的析构函数
子类的拷贝构造和拷贝赋值:
默认的子类拷贝构造函数会调用父类的拷贝构造
如果手动实现默认是调用无参构造 如果有需要调用父类的拷贝构造函数,
需要手动在初始化列表中调用父类的拷贝构造
默认的子类的拷贝赋值函数会调用父类的拷贝赋值函数
如果手动实现将不会再调用父类的拷贝赋值函数
需要手动调用: static_cast<父类*>(this)->operator=(实参);
父类::opeartor=(实参);
子类属性和父类属性同名时,访问时根据局部优先原则 直接访问到的是 子类自己的
如果要指定访问父类的同名属性 则可以用 父类名::属性名 方式访问
子类对象 is A 父类对象(男人也是人)
子类类型可以转换成父类类型对象
父类类型 对象 = 子类对象; //用子类对象来拷贝构造父类类型对象
父类类型的对象 = 子类对象; //通过父类的拷贝赋值进行赋值
任何一个子类对象中 都有 一个父类子对象
父类指针 可以指向子类对象 (父类指针不可以隐式转换成子类类型指针)
子类的指针可以隐式转换成父类类型的指针
但是: 隐式转换成父类类型的指针 两个值 可以不一样
父类类型的指针 指向的不是子类对象的首地址 而是指向父类子对象中的首地址
父类指针不可以隐式转换成子类类型指针
但是: 可以通过static_cast<> 进行显示转换
通过static_cast<>静态显示转换 能够重新重到原来子类对象的首地址
但是通过reinterpret_cast<>重解释显示转换 不能得到 原来子类对象的首地址
static_cast<> 转换并不会检验 父类指针所指向的对象 是否是 目标类型的对象 非常危险
肯定是可以成功 但后续可能引发非常严重的错误
父类引用 可以引用子类对象
可以用父类的引用 直接 引用子类对象
实际上 父类的引用是引用子类对象中的 父类子对象
反之则不行 但可以用 静态类型转换
父类的指针指向子类对象 或者 父类的引用引用子类对象
通过父类指针和引用 只能 访问到父类中的属性 和 方法
用父类的指针指向一个new出来的子类对象时
在delete这个指针时 只会调用父类自己的析构函数
如果子类中有new动态内存 则会有内存泄露
多态: = 虚函数+(指针/引用)