多态
多态的前提是赋值兼容
赋值兼容只发生在共有(public)派生的父子关系中
子类对象赋给父类对象
子类对象赋给父类的引用
子类对象的地址赋给父类指针
函数重载实际上是静多态,是在编译阶段决定的
动多态是在运行时决定的
1.父类中有虚函数(虚公共接口)
2.子类中覆写(override)了父类的虚函数
3.将子类对象地址赋给服了父类的指针,并发生虚函数调用
两种情况不能发生多态:
1.父类的指针在父类的构造器或者析构器中(对于在构造器中,则此时子类对象尚未产生完成,在析构器中则此时子类对象已经不存在了,被析构了) 因为构造时先构造父类对象 析构时先析构子类对象
2.在父类
声明虚函数,在函数声明前面加virtual
和static函数一样
虚函数声明 virtual void func() 声明型关键字
覆写(override)
重载:同一个作用域中,函数名相同,参数列表不同
shadow:发生在父子类中的同名成员
override:发生在父子类中,父类中有virtual声明的函数,与子类中同参、同名、同返回的函数,之间构成覆写
多态一般只用指针,因为引用一旦确定关系就不能改了
被覆写的函数,是不是同父类的访问方式一致?
子类中覆写的函数,可以为任意的访问类型,依据子类需求决定
纯虚函数
格式: virtual void draw() = 0;
纯虚函数没有实现体,含有纯虚函数的类称为抽象基类,抽象基类不可以实例化
作用就是给族类提供接口
Java中吧抽象基类叫做接口(interface)
虚析构,就是为了析构完全(在delete父类指针的时候,将子类对象析构完全)
党一个类中有虚函数的时候,请将其析构函数一并virtual
面试问的多态内容
多态的架构方面?
多态的本质?
依赖倒置
指针数组最后一个通常是NULL
多态:
实现在动态绑定
牺牲了一些空间和效率
构造器不能声明为虚函数?
构造器承担着虚函数表的构建
typeid 和 dynamic_cast 运算符只用于父子类继承中
只要含有虚函数的类,他的析构一定是虚的
static_cast 可以upcast也可以downcast 也就是父类子类指针可以互转
dynamic_cast 只用于含有虚函数的父子类中,只有downcast,是不是得到其目标类型,如果是,返回其指针, 不是则返回NULL
reinterpreter_cast 先把原指针转化为void* 然后再转成目标类型指针 不安全
模板
模板在开发中用的不多,模板是高度抽象化的事情
学习模板主要是为了了解STL,方便以后使用
既然提供了函数模板,最好就不要提供普通函数,否则容易出现二义性
类模板
类模板的成员函数在模板调用时才创建
vector会用的效率很高,不会用的效率很低 容量以2的幂次方增长
底层实际使用malloc来产生新空间
更高级的是自己定制内存增长策略