类与对象【多态】------多态、虚析构和纯虚析构、纯虚函数和抽象类

多态分为两类:

        1、静态多态——函数重载和运算符重载,复用函数名

        2、动态多态——派生类和虚函数实行运行多态

静态多态和动态多态区别:

        1、静态多态的函数地址早绑定——编译阶段确定函数地址

        2、动态多态的函数地址晚绑定——运行阶段确定函数地址

动态多态的条件:

        1、有继承关系

        2、子类重写父类的虚函数  

地址早绑定时:
class animal{
public:
    void speak(){
        cout<<"11111"<<endl;
    }
};

地址晚绑定时:
class animal{
public:
    virtual void speak(){
        cout<<"11111"<<endl;
    }
};

class cat : public animal{
public:
    void speak(){
        cout<<"cat11111"<<endl
    }
}



void dospeak(animal &a){//父类做形参,可以直接传递子类
    a.speak();
}//早绑定时,此时传递参数为cat类,那么一定输出11111
//晚绑定时,此时传递参数为cat类,那么一定输出cat11111

动态多态的底层原理 :

        1、vfptr指向记录虚函数的地址

        2、当子类重写了父类的虚函数,那么vfptr指向的虚函数地址覆盖为子函数(此时的子函数不写虚函数关键字也是虚函数)

class animal{
public:
    void speak(){
        cout<<1111<<endl;
    }
};//类的函数和变量分开存储,函数只有一份;此时相当于空对象,为一字节

class animal{
public:
    virtual void speak(){
        cout<<1111<<endl;
    }
};//此时增加了一个虚函数指针vfptr——占四个字节

纯虚函数和抽象类

 纯虚函数:

        virtual 返回值类型 函数名 (参数列表) =  0;//一般是基本不会被调用的父类虚函数

 抽象类:

        有纯虚函数的类叫抽象类

抽象类的特点:

        1、无法实例化对象

        2、子类必须重写抽象类的纯虚函数,否则也是抽象类 

 虚析构和纯虚析构

         多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构函数

        解决方法:虚析构和纯虚析构

class animal{
public:
    virtual void speak(){
        cout<<"11111"<<endl;
    }
};

class cat : public animal{
public:
    void speak(){
        cout<<*name<<" cat11111"<<endl
    }

    ~cat(){
        delete name;
        name = NULL;
    }

    string *name;
}

animal * a = new cat("tom");
a->speak();
delete a;//父类指针在析构时,不会调用子类的析构函数,导致子类在堆区的数据发生内存泄漏

利用虚析构解决父类指针释放子类对象时不干净的问题
virtual animal::~animal(){
    
}
纯虚析构:
virtual animal::~animal() = 0;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值