运行时多态和编译时多态
多态可以分为静多态和动多态
- 静多态
静多态在编译时就确定调用函数的类型,函数重载就是一个典型的静多态
函数重载:
- 函数名相同
- 参数的个数不同,参数的类型不同,参数的顺序不同,均可构成重载
- 返回类型不同不可以构成重载
- 相同的范围 (在同一个类中)
- 动多态
在运行时才能确定调用哪个函数,动态绑定。 实际上是子类重新定义了父类的虚函数, 父类的指针就根据赋给它的不同子类的指针, 动态的调用属于子类的虚函数, 这样的函数调用在编译期无法确定。也就是覆盖。
覆盖: 派生类重新定义父类中的函数, 函数名,参数列表,返回类型都必须和父类中被覆盖的函数严格一致, 只有函数体不同。
- 函数名相同
- 参数列表相同
- 基类函数必须有virtual关键字
隐藏 : 派生类的函数屏蔽了与其同名的基类函数。 规则如下:
- 如果派生类的函数名与基类的函数名相同, 但是参数不同, 此时不论有没有virtual 关键字,基类的函数将被隐藏 (注意与重载的区别)
- 如果派生类的函数名和参数列表都和基类的函数相同, 但是基类函数没有virtual关键字,基类的函数会被隐藏, (注意与覆盖/重写 混淆)
总结:
-
运行期多态:
- 依赖于虚函数,父类 指针在运行期通过虚函数指针以及虚函数表确定 该类虚函数的真正实现
-
编译期多态:
- 通过 模板具现化 和 函数重载解析实现的。 不同的模板参数具现化导致调用不同的函数。 都是在编译期间可以通过推导确定运行的函数
-
优缺点对比:
- 优点:
- 运行期多态:
- 面对对象设计, 处理一个集成体系下的多个类集合
- 编译期多态:
- 泛型编程概念,STL
- 在编译期完成多态,提高运行效率
- 具有很强适配性与松耦合性
- 运行期多态:
- 缺点:
- 运行期多态:
- 运行期间与虚函数绑定,增加了运行开销
- 继承层次增大时,对接口的修改容易影响继承层次
- 由于在运行时确定,编译器无法对虚函数进行优化
- 编译期多态
- 代码可读性降低,代码调试困难
- 无法实现模板的分离编译,增加了编译时间
- 运行期多态:
参考:
- 优点: