C++多态

一.多态的基本语法

c++中的多态分为两类

静态多态:函数重载和运算符重载属于静态多态,复用函数名

动态多态:派生类和虚函数实现运行时多态

静态多态和动态多态区别

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

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

我们先来看静态多态的实际例子

#include<iostream>

using namespace std;

class Animal{
public:
void speak(){
    cout<< "动物在说话"<<endl;
}
};

class Cat :  public Animal{
public: 
void speak(){
    cout<<"小猫在说话"<<endl;
}
};


void doSpeak(Animal &animal){
    animal.speak();
}

int main(){
    Cat cat;
    doSpeak(cat);
}

这里我们创建了一个doSpeak函数,它相当于父类的引用指向子类的对象

我们来看看运行结果

这里运行的是父类中的speak函数,这是因为静态多态的函数地址早绑定- 编译阶段确定函数地址

如果这时想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段绑定,需要在运行阶段进行绑定-地址晚绑定

所以我们要进行动态多态

代码如下:

#include<iostream>

using namespace std;

class Animal{
public:
void  virtual speak(){
    cout<< "动物在说话"<<endl;
}
};

class Cat :  public Animal{
public: 
void speak(){
    cout<<"小猫在说话"<<endl;
}
};
class Dog :  public Animal{
public: 
void speak(){
    cout<<"小狗在说话"<<endl;
}
};

void doSpeak(Animal &animal){
    animal.speak();
}

int main(){
    Cat cat;
    doSpeak(cat);

    Dog dog;
    doSpeak(dog);
}

运行结果:

我们将父类Animal的speak函数定义成虚函数,这样就是动态多态

总结一下动态多态的满足条件:

1.有继承关系

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

3.父类引用指向子类的对象

二.虚析构与纯虚析构

当父类的析构函数不是虚析构函数时,如果通过父类的指针来删除一个派生类的对象,那么将只会调用父类的析构函数,而不会调用派生类的析构函数。这会导致派生类部分的资源(如动态分配的内存、文件句柄、网络连接等)没有被正确释放,从而造成内存泄漏或其他资源泄漏。

#include<iostream>
#include<string>

using namespace std;

class Animal
{
public:
    Animal()
    {
        cout << "这是Animal的构造" << endl;
    }
    ~Animal()
    {
        cout << "这是Animal的析构" << endl;
    }

    virtual void speak() = 0;

    
};

class Cat : public Animal
{
public:
    Cat(string name)
    {
        cout << "这是Cat的构造" << endl;
        m_Cat = new string(name);
    }
    ~Cat()
    {
        cout << "这是Cat的析构" << endl;
    }
    
    virtual void speak()
    {
        cout << *m_Cat << "小猫在说话" <<endl;
    }

    string *m_Cat;

};

void test01()
{
    Animal * cat1 = new Cat("Tom");

    cat1->speak();

    delete cat1;
}

int main()
{
    test01();
}

我们注意这里父类Animal的析构函数不是虚析构

~Animal()

    {

        cout << "这是Animal的析构" << endl;

    }

这里就没有调用Cat的析构函数,最终导致内存泄露。而将Animal的析构函数改为虚析构时,

virtual ~Animal()

    {

        cout << "这是Animal的析构" << endl;

    }

这里就可以正常调用Cat的析构函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值