virtual修饰类的成员函数/析构函数

文章讨论了C++中virtual关键字在成员函数和析构函数上的区别。当成员函数被声明为virtual时,基类指针能够调用子类的重写方法,实现多态。如果不加virtual,调用的是基类的方法。对于析构函数,不加virtual会导致只有基类的部分被析构,子类的资源可能无法正确释放。当析构函数是virtual时,通过基类指针删除子类对象会确保子类的析构函数也被调用,从而完整地释放所有资源。
摘要由CSDN通过智能技术生成

1.对类的成员函数加 virtual 和不加 virtual的区别

看这么一个例子

class Animal {
public:
    void makeSound() {
        cout << "Animal sound!" << endl;
    }    
};

class Dog: public Animal {
public:
    void makeSound() {
        cout << "Bark!" << endl; 
    }
};

int main() {    
    Animal* a = new Dog;  
    a->makeSound();  // Animal sound!
    
    Dog* d = new Dog;
    d->makeSound();  // Bark!
}

此时输出:
在这里插入图片描述
也就是说尽管基类指针指向子类对象,但是调用的还是基类指针的行为。
而将 makeSound声明为virtual时:

class Animal {
public:
    virtual void makeSound() {
        cout << "Animal sound!" << endl;
    }    
};

class Dog: public Animal {
public:
    void makeSound() {
        cout << "Bark!" << endl; 
    }
};

int main() {    
    Animal* a = new Dog;  
    a->makeSound();  // Animal sound!
    
    Dog* d = new Dog;
    d->makeSound();  // Bark!
}

此时才会出现多态的行为,即基类指针指向子类对象会调用子类的行为。

在这里插入图片描述

2.对类的析构函数函数加 virtual 和不加 virtual的区别:

对析构函数不加virtual
例子:

#include<iostream>
using namespace std;
class Base {
public:
    ~Base() {
        cout<<"Base deconstructor"<<endl;
    }     // 析构函数 
};

class Derived: public Base {
   int *p;  
public:
    Derived() {
        p = new int(10);
    }
    ~Derived(){
        delete p;
        cout<<"Derived deconstructor"<<endl;
    }
};

int main(){
    Derived *d = new Derived(); 
    Base *b = new Derived(); 
    delete d;  // 只释放Base中的内存,不释放p
    cout<<endl;
    delete b;
    
}

此时输出结果为:
在这里插入图片描述
可以看到如果是子类指针指向子类对象先调用自己的析构函数,再调用基类的析构函数
但如果是基类指针指向子类对象,则只调用基类的析构函数

当加上virtual后:

#include<iostream>
using namespace std;
class Base {
public:
    virtual ~Base() {
        cout<<"Base deconstructor"<<endl;
    }     // 析构函数 
};

class Derived: public Base {
   int *p;  
public:
    Derived() {
        p = new int(10);
    }
    ~Derived(){
        delete p;
        cout<<"Derived deconstructor"<<endl;
    }
};

int main(){
    Derived *d = new Derived(); 
    Base *b = new Derived(); 
    delete d;  // 只释放Base中的内存,不释放p
    cout<<endl;
    delete b;
    
}

输出:
在这里插入图片描述
此时delete 基类指针时,可以发现子类的析构函数调用。

3.总结

不加virtual: 只释放基类内存,执行基类语义
加 virtual: 释放派生类和基类内存,并且先执行派生类重写的语义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值