美文网首页
C++中基类的析构函数为什么要用virtual虚析构函数?

C++中基类的析构函数为什么要用virtual虚析构函数?

作者: MemetGhini | 来源:发表于2022-05-17 08:33 被阅读0次

    析构函数是对象生存期终结时调用的特殊成员函数。析构函数的目的是释放对象可能在它的生存期间获得的资源。

    C++中基类采用virtual虚析构函数是为了防止内存泄漏。如果父类的析构函数是非虚的,当删除父类指针指向的子类对象时就不会去调用子类的析构函数,只调用父类的。这时候在子类的资源不能获得释放,发生了内存泄漏,包括成员对象,堆中开辟的内存。

    代码实例:

    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
        Base() {
            cout << "🙎父类被构造" << endl;
        };
    
        ~Base() //Base的析构函数
        {
            cout << "🙎❌父类被析构~" << endl;
        };
        virtual void func()
        {
            cout << "父类方法被调用func" << endl;
        };
    };
    
    class Test
    {
    public:
        Test() {
            cout << "✅成员对象被构造" << endl;
        }
    
        ~Test() {
            cout << "❌成员对象被析构" << endl;
        }
    };
    
    class Derived : public Base
    {
    public:
        Derived() {
            cout << "👶子类被构造" << endl;
        };
    
        ~Derived() //Derived的析构函数
        {
            cout << "👶❌子类被析构~" << endl;
        };
        void func() override
        {
            cout << "子类方法被调用func" << endl;
        };
        Test t;
    };
    
    int main()
    {
        Derived *p1 = new Derived(); //Derived类的指针
        p1->func();
        delete p1;
    
        cout << "\n<<<<<<<<<<<>>>>>>>>>>>\n" << endl;
    
        Base *p2 = new Derived(); //Base类的指针
        p2->func();
        delete p2;
    
        return 0;
    }
    

    执行结果:

    🙎父类被构造
    ✅成员对象被构造
    👶子类被构造
    子类方法被调用func
    👶❌子类被析构~
    ❌成员对象被析构
    🙎❌父类被析构~
    
    <<<<<<<<<<<>>>>>>>>>>>
    
    🙎父类被构造
    ✅成员对象被构造
    👶子类被构造
    子类方法被调用func
    🙎❌父类被析构~
    

    可以看到父类类型的指针指向父类析构函数能够被正常调用,子类类型的指针指向父类子类析构函数没有被调用,成员函数的析构也没有被调用。
    如果把基类的析构函数声明为虚函数virtual,并子类override父类的析构函数再来执行。

    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
        Base() {
            cout << "🙎父类被构造" << endl;
        };
    
        virtual ~Base() //Base的析构函数
        {
            cout << "🙎❌父类被析构~" << endl;
        };
        virtual void func()
        {
            cout << "父类方法被调用func" << endl;
        };
    };
    
    class Test
    {
    public:
        Test() {
            cout << "✅成员对象被构造" << endl;
        }
    
        ~Test() {
            cout << "❌成员对象被析构" << endl;
        }
    };
    
    class Derived : public Base
    {
    public:
        Derived() {
            cout << "👶子类被构造" << endl;
        };
    
        ~Derived() override //Derived的析构函数
        {
            cout << "👶❌子类被析构~" << endl;
        };
        void func() override
        {
            cout << "子类方法被调用func" << endl;
        };
        Test t;
    };
    
    int main()
    {
        Derived *p1 = new Derived(); //Derived类的指针
        p1->func();
        delete p1;
    
        cout << "\n<<<<<<<<<<<>>>>>>>>>>>\n" << endl;
    
        Base *p2 = new Derived(); //Base类的指针
        p2->func();
        delete p2;
    
        return 0;
    }
    

    执行结果:

    🙎父类被构造
    ✅成员对象被构造
    👶子类被构造
    子类方法被调用func
    👶❌子类被析构~
    ❌成员对象被析构
    🙎❌父类被析构~
    
    <<<<<<<<<<<>>>>>>>>>>>
    
    🙎父类被构造
    ✅成员对象被构造
    👶子类被构造
    子类方法被调用func
    👶❌子类被析构~
    ❌成员对象被析构
    🙎❌父类被析构~
    

    很明显下面这种才是符合预期的,父类子类都被析构了。

    相关文章

      网友评论

          本文标题:C++中基类的析构函数为什么要用virtual虚析构函数?

          本文链接:https://www.haomeiwen.com/subject/dkgourtx.html