C++继承
代码重用
组合(has-a)
A类里含有B类的成员
继承(is-a)
class 派生类名:继承方式 基类名
{派生类新增成员的声明;}
继承是使用已经编写好的类来创建新类,新的类具有原有类的所有属性和操作,也可以在友元类的基础上做一些修改和增补。
新类称为派生类或子类,原有类称为基类或父类
派生类是基类的具体化
继承规则
公有继承:
基类的公有成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类的私有成员。
public 作用:传承接口间接的传承了数据(protected)。
派生类
派生类的组成
一类是从基类继承过来的(共性),一类是自己增加的成员(个性)。
派生类的构造函数(执行顺序)
基类继承而来的成员的初始化工作还是由基类构造函数完成,派生类新增的成员在派生类的构造函数中初始化。
派生类构造函数执行的次序
基类–>成员对象–>子类
基类中没有默认构造函数(无参),那么在派生类的构造函数中必须显示调用基类构造函数,以初始化基类成员。
调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左到右);
调用内嵌成员对象的构造函数,调用顺序按照它们在类中声明的顺序;
派生类拷贝构造函数(调用传参)
派生类::派生类(const 派生类& another):基类(another),派生类新成员(another.新成员)
派生类中的默认拷贝构造器会调用父类中默认或自实现拷贝构造器
若派生类中自实现拷贝构造器,则必须显示的调用父类的拷贝构造器。
派生类拷贝赋值运算符(显示调用父类:private继承的时候)
派生类可继承、可重载
派生类拷贝赋值运算符中显示调用,无则隐式调用
派生类的友元函数(不能继承,但是通过强制类型转化)
友元函数并非类成员,因引不能被继承
派生类访问基类的友元函数:将派生类的指针或者引用强制转化为基类指针或者引用
派生类的析构函数(执行顺序)
析构函数的执行顺序与构造函数相反。
子类->成员对象->基类
派生类成员函数
函数重载
函数遮蔽
派生类成员函数与基类成员函数一摸一样–默认调用派生类的方法
通过派生类对象访问基类的同名函数 对象名.基类名::函数名
多继承
多继承语法:class 派生类名: 访问控制符 基类名1,访问控制符 基类名2
{
数据成员和成员函数声明;
}
多重继承的二义性
虚基类和虚继承机制,实现了在多继承中只保留一份共同成员,从而解决了多继承导致的二义性问题
基类、派生类的转换
C++向上转型:类其实也是一种数据类型,也可以发生数据类型转换,不过这种转换只有在基类和派生类之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型(Upcasting)。相应地,将基类赋值给派生类称为向下转型(Downcasting)。
将派生类对象赋值给基类对象
将派生类指针赋值给基类
类型兼容性原则
子类对象可以当作父类对象使用
子类对象可以直接赋值给父类对象
子类对象可以直接初始化父类对象
父类指针可以直接指向子类对象
父类引用可以直接引用子类对象
C++多态
多态
定义:
所谓的多态(polymorphism)是指,由继承而产生的相关的不同的类,其对象对同一消息会作出不同的响应。
作用:
能增加程序的灵活性。可以减轻系统升级,维护,调试的工作量和复杂度.–提高代码的扩展性
多态形成的条件
父类中有虚函数。
子类override(覆写)父类中的虚函数。
通过己被子类对象赋值的父类指针或引用,调用共用接口
虚函数
注意事项
1.基类中用virual 声明成员函数为虚函数。类外实现虚函数时,不必再加virtual.
2.在派生类中重新定义此函数称为覆写,要求函数名,返值类型,函数参数个数及类型全部匹配
3.为了避免在派生类写错虚函数,可在派生类里的虚函数中添加override修饰,确保该函数为虚函数并覆写来自基类的虚函数。
若干限制
只有类的成员函数才能声明为虚函数
静态成员函数不能是虚函数
内联函数不能是虚函数
构造函数不能是虚函数
析构函数可以是虚函数且通常声明为虚函数。
为什么将基类析构函数定义为虚析构函数?
当你可能通过基类指针删除派生类对象时
纯虚函数
定义:virtual 函数名(形参) = 0;
纯虚函数只有声明,没有实现,被“初始化”为0。
抽象类
定义:含有纯虚函数的类,称为抽象基类,不可实列化。即不能创建对象
作用(接口):被继承,提供族类的公共接口
注:纯虚函数,而在派生类中没有对该函数定义,则该虚函数在派生类中仍然为纯虚函数,派生类仍然为纯虚基类。
运行时类型信息(RTTI)
运算符typeid
1.运算符typeid 返回包含操作数数据类型信息的type_info 对象的一个引用,信息中包括数据类型的名称
2.其中type_info 重载了操作符==, !=,分别用来比较是否相等、不等,函数name()返回类型名称
3.type_info 的拷贝和赋值均是私有的,故不可拷贝和赋值
多态下使用typeid 时要注意的问题:
1.确保基类定义了至少一个虚函数(虚析构也算)。
2.不要将typeid 作用于指针,应该作用于引用,或解引用的指针。
3.type_info 类型,其拷贝构造函数和赋值运算函数都声明为private 了,这意味着其不能用于stl 容器
dynamic_cast
作用
1.若对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;
2.若对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全
对象模型-多态实现原理分析及对象大小
案例实现
通讯录