多态

来源:互联网 发布:360数据恢复精灵 编辑:程序博客网 时间:2024/06/03 22:55

多态:不同内容的函数可以共用同一个函数名,运行时选择函数的版本(传入函数的对象类型决定执行函数版本)

  • 静态多态性:函数和运算符重载(overloaded:同一作用域内名字相同,形参列表不同的函数CP207)

    1. 不能只有返回类型不同
    2. 编译器无法区分顶层const,只能区分底层constCP208
    3. 确定重载函数更容易理解
    4. function matching(函数匹配):最佳匹配;二义性调用
    5. 避免在函数声明于局部作用域(内层作用域会隐藏外层作用域的同名实体,且编译器先进行名字查找,再进行类型检查)
  • 动态多态性:virtual function(虚函数)
    dynamic binding(动态绑定)CP527
    只有通过指针或者引用调用虚函数时发生。CP537

    1. 在函数声明前加上virtual
    2. 派生类虚函数的返回类型和形参列表必须和基类一致,除非返回类型为类本身的引用或指针。CP537否则编译器无法通过动态类型确定应该调用的函数版本。
    3. 基类和派生类的默认实参最好一致。
    4. 在成员函数或友元中可以使用作用域运算符强制执行某一版本。
    5. 基类通常要定义虚析构函数。E07
      考虑到在delete指针时,如果指针的静态类型和动态类型不一样,编译器能够调用动态类型的析构函数版本CP552。所以不要继承不带虚析构函数的类。
      EP42当某类不作为基类时,虚析构函数会增加额外的内存开销

    6. 构造函数之外的非静态函数都可以是虚函数

    7. 如果派生类没有override会直接继承。CP530
      当派生类函数覆盖了继承的虚函数,形参类型必须和被覆盖的函数一致。(考虑E32)可以使用override标记派生类的函数。
void mf1() override;

当由于失误没有覆盖时,编译器将报错。CP538
如果不希望某个基类函数被覆盖,可以把函数定义成final。(即使该函数不为虚函数)

  • 纯虚函数:无需定义
void mf1()=0;//只能出现在类内部的声明处

纯虚函数:含有(未覆盖)纯虚函数。由于函数没有定义,所以无法生成该类对象。当其派生类覆盖(定义)该函数后才能生成对象。
重构:类C直接继承于类A,现抽象基类B继承于类A,类C再继承于类B。CP543
- E35 虚函数的替代方案

  • NVI(non-virtual Interface)
class A{public:   void mf1()//虚函数的外覆器   {      …//事前工作      dothing();//进行实际工作//事后工作   }   …private://或者protected  virtual void dothing()  {     …  }};
  • Strategy模式
    在类中定义1个函数指针来调用类外函数。注意该函数无法访问类的非公有成员。也可以降低封装性使该函数成为友元。