重载运算符
1、什么是重载运算符 重载运算符就是使自定义类型能够像内置类型那样,能够用运算符进行操作。同时将运算符看作是一种特殊的函数,操作数是函数的参数,运算结果是函数的返回值,函数名由关键字operator 和其后要定义的运算符组成。例:operator+
2、类外与类内区别 1)对于类成员运算符函数,this 指向的对象被作为运算符的第一个操作数(左),一元无需含参,二元需有右操作数 2)对于非成员运算符函数 一元运算符要提供一个类类型的参数 二元运算符需要提供两个参数分别作为左、右操作数,其中至少一个参数必须是类类型的,通常声明为类的友元,以便访问私有数据成员。
3、注意点 1)只有至少一个操作数是用户自定义类型时,才可能调用重载的运算符 2)不能滥用运算符重载!!!
4、不可以运算符重载的运算符 逻辑与(&&)、逻辑或(||)、逗号运算符(,) 取值符(&)
5、运算符选择 重载输入输出,定义移位运算符>>和<<;检查相等性,定义operator==; 重载小于号,定义operator<;
6、成员与友元选择 1)函数成员:赋值(=)、下标([])、函数调用(())和成员函数访问箭头(->)、 复合赋值运算符、 改变对象状态的运算符或者与给定类型密切相关的运算符 2) 非函数成员:具有对称性的运算符可能转换两个操作数中的任何一个、重载移位运算符<<和>>用于对象的I/O 操作时,左操作数是标准库流对象,右操作数是类类型的对象
7、自增与自减:后缀形式的自增和自减比前缀形式多一个int参数。
8、 参数的const 使用 对于类类型的参数,如果仅仅只是读参数的值,而不改变参数,const传递,同时将其定义为const成员函数。
9、返回值的类型 :取决于运算符的具体含义 1)如果使用运算符的结果是产生一个新值,就需要产生一个作为返回值的新对象,通过传值方式返回,通常由const限定。 2)如果函数返回的是操作数对象,则通常以引用方式返回,根据是否希望对返回的对象进行操作来决定是否返回const引用
对于上面两点需注意:1、所有赋值运算符均改变左值 2、逻辑运算符和关系运算符最好返回bool值
10、重载输入输出模板:istream& operator>>(istream&, type&); ostream& operator<<(ostream&, const type&);
11、如何调用:调用运算符必须是成员函数
继承与组合
————组合:将一个类的对象作为另一个类的成员。 1、 成员对象嵌入方式 1)如果嵌入对象作为新类的公有成员,可以向包含的成员对象发送消息。 2)如果将嵌入对象作为新类的私有成员,它是新类内部实现的一部分,新类只向外部提供自己的接口,隐藏了包含的嵌入成员对象。
2、成员对象创建与撤销 1)创建包含对象成员的组合对象时,会执行成员类的构造函数初始化对象成员(成员对象的初始化使用初始化列表语法)先执行嵌入对象的构造函数 2) 当组合对象被撤销时,会执行其析构函数,成员对象的析构函数也会被执行,析构函数的执行次序和构造函数相反
3、复用类实现 :在原有类上更改,或者重新包装
————继承:在已有类的基础上继承得到新类型,这个新类型自动拥有已有类的特性,并可以修改继承到的特性或者增加自己 的新特性
1、主要概念:被继承的已有类称为基类; 继承得到的新类称为派生类; 派生类再被继承,这样构成的层次结构称为继承层次
2、类继承关系的语法形式 : class 派生类名 : 基类名表 //基类名表的构成 访问控制 基类名1, 访问控制 基类名2 ,… , 访问控制 基类名 { 数据成员和成员函数声明 };
3、访问控制 三种: public 将基类的公有成员转换为派生类的公有成员,保护成员仍为保护成员 private 将基类的公有成员和保护成员转换为派生类私有成员 protected 将基类的公有成员和保护成员转换为派生类保护成员
4、派生类的生成过程经历了三个步骤: 吸收基类成员 改造基类成员 添加派生类新成员
5、重名成员:派生类定义与基类的同名函数来隐藏基类函数,如果想使用基类被隐藏的函数,可以使用 基类名::函数
6、基类初始化: 在创建派生类对象时用指定参数调用基类的构造函数来初始化派生类继承基类的数据 派生类构造函数声明为 派生类构造函数 ( 变元表 ) : 基类 ( 变元表 ) , 对象成员1( 变元表 ) … 对象成员n ( 变元表 ) ; 构造函数执行顺序:基类 对象成员 派生类
7、继承规则
基类的构造函数和析构函数不能被继承
如果基类无无参的构造函数,派生类必须定义构造函数
如果派生类的基类也是派生类,则每个派生类只负责直接基类的构造
8、多继承
***多继承
class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n
{
数据成员和成员函数声明
};
***多继承列表初始化
派生类名(参数总表):基类名1(参数表1),基类名2(参数表2),…,基类名m(参数表m),派类成员n(n)...
{
// 派生类新增部分成员的初始化
}
9、赋值兼容的可行性
1) 派生类的对象可以赋给基类对象(强制类型转换)
2)派生类的对象可以初始化基类的引用
3)派生类的对象的地址可以赋给基类类型的指针 4)在替代之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员
虚函数与多态
1、虚函数与多态性
定义:多态性是指一个名字,多种语义;或界面相同,多种实现。
2、重载函数:多态性的一种简单形式,同时虚函数允许函数调用与函数体的联系在运行时才进行,称为动态联编。
3、冠以关键字 virtual 的成员函数称为虚函数,实现运行时多态的关键首先是要说明虚函数,另外,必须用 基类指针调用派生类的不同实现版本,派生类对基类中声明虚函数重新定义时,关键字virtual可以不写。
4、需要注意的是 一般通过基类指针访问虚函数时才能体现多态性。
一个虚函数无论被继承多少次,保持其虚函数特性。
虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态函数
虚函数和基类指针
1、基类指针虽然获取派生类对象地址,却只能访问派生类从基类继承的成员 2、一个虚函数,在派生类层界面相同的重载函数都保持虚特性
3、虚函数必须是类的成员函数
虚函数的重载特性
在派生类中重载基类的虚函数要求函数名、返回类型、参数个数、参数类型和顺序完全相同
纯虚函数和抽象类
纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。纯虚函数为各派生类提供一个公共界面 纯虚函数说明形式: virtual 类型 函数名(参数表)= 0 ;