多态分为两类(一般指动态多态)
    静态多态:如函数重载和运算符重载
    动态多态:派生类和虚函数实现运行时多态
    区别在于静态多态的函数地址编译阶段绑定 动态多态的函数地址运行阶段确定
    
    
 动态多态的条件
    1.有继承关系
    2.子类重写(完全一致不重载)父类的虚函数    (父类必须加virtual 子类可不加  加到声明即可,此时实现可加可不加)
    
 静态多态的情况
    定义一个全局函数
    void speak(Animal &animal)
    {
        animal.speak();
    }
    
    cat类继承Animal类时 且两者都有自己的speak函数 子类调用这个全局函数的时候(子类与父类是同一个类型 所以能调用同一个全局函数)
    cat t;
    speak(t);
    此时依然调用的是Animal的speak方法  因为地址编译即分配了
    
    
 动态多态
    若想调用cat的speak函数则 在Animal的函数前加一个virtual关键字 让它变成虚函数 此时会根据类调用自己对应的speak函数
    
 vfptr 虚函数指针
    当子类重写父类的虚函数 子类中的虚函数表会替换成子类的虚函数地址
    
    
 多态的好处:
    1.组织结构清晰
    2.可读性强
    3.对于前期和后期拓展以及维护性高
    
    开闭原则:对扩展进行开发,对修改进行关闭,即尽量不修改代码,而是扩展


 纯虚函数和抽象类
    在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可将虚函数改为纯虚函数
    语法:virtual 返回值类型 函数名(参数列表)=0;
    
    当类中有了纯虚函数,这个类也称为抽象类
    抽象类的特点:无法实例化对象,子类必须重写抽象类中的纯虚函数,否则也属于抽象类
    
 虚析构和纯虚析构
    多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时不会调用到子类的析构代码
    解决办法:将父类中的析构函数改为虚析构或者纯虚析构
    
    虚析构语法:virtual ~类名(){}
    纯虚析构语法: 声明:virtual ~类名()=0;  实现:类名::~类名(){}
    
    
    虚析构和纯虚析构的共性:
    1.可以解决父类指针释放子类对象
    2.都需要有具体的函数实现
    
    虚析构和纯虚析构的区别:
    如果是纯虚构,该类属于抽象类,无法实例化对象

    

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐