C++ 虚析构函数

 

Virtual 关键字起到什么作用

借鉴网友blog, 了解了虚析构函数的作用:

  虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。

  也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的。

 

 c++中的函数调用默认不适用动态绑定,要触发动态绑定,必须满足两个条件:第一指定为虚函数; 第二通过基类类型的引用或指针调用 

Virtual继承及示例和注意事项 --》 注意, 加了virtual的虚虚构函数和不加virtual的析构函数结果不一样哦

virtual可用来定义类函数和应用到虚继承中

注意:

  有元函数、构造函数、static静态函数不能用virtual关键字修饰。普通成员函数和析构函数可以用virtual关键字修饰。

  

#include<stdlib.h>
#include<iostream>

using namespace std;

class GrandFather {
public:
    GrandFather() {}

    virtual void fun() {
        cout << "GrandFather call function" << endl;
    }
};

class Father : public GrandFather {
public:
    Father() {}

    void fun() {
        cout << "Father call function" << endl;
    }
};

class Son : public Father {
public:
    Son() {}

    void fun() {
        cout << "Son call function" << endl;
    }
};

void Print(GrandFather *father) {
    father->fun();
}

int main(int argc, char const *argv[]) {
    Father *pfather = new Son;
    pfather->fun();
    delete pfather;

//    GrandFather *grandfather = new Father;
//    Print(grandfather);

    return 0;
}
带有自定义virtual的类自定义虚函数

 

多继承的带virtual的虚析构函数

#include <iostream>

using namespace std;

class GraphFather {
private:

public:
    GraphFather(){
        cout << "GraphFather structure" << '\n';
    };
    virtual ~GraphFather(){
        cout << "GraphFather deconstruction" << '\n';
    };
};


class Father : public GraphFather {
private:

public:
    Father(){
        cout << "Father structure" << "\n";
    };
    ~Father(){
        cout << "Father deconstruction" << "\n";
    };
};


class Son: public Father {
private:

public:
    Son(){
        cout << "Son structure" << "\n";
    };
    ~Son(){
        cout << "Son Deconstruction" << "\n";
    };
};


int main(int argc, char const *argv[]){
    Father *gfather = new Son;
    delete gfather;


    return 0;
};
带virtual的虚析构函数

 

返回值:

Son call function

 

先看第一个例子:

  

#include <iostream>

using namespace std;

class GraphFather {
private:

public:
    GraphFather(){
        cout << "GraphFather structure" << '\n';
    };
    ~GraphFather(){
        cout << "GraphFather deconstruction" << '\n';
    };
};


class Father : public GraphFather {
private:

public:
    Father(){
        cout << "Father structure" << "\n";
    };
    ~Father(){
        cout << "Father deconstruction" << "\n";
    };
};


class Son: public Father {
private:

public:
    Son(){
        cout << "Son structure" << "\n";
    };
    ~Son(){
        cout << "Son Deconstruction" << "\n";
    };
};


int main(int argc, char const *argv[]){
    GraphFather *gfather = new Son;
    delete gfather;
    cout << "================" << '\n';
    Father *father = new Son;
    delete father;
    cout << "================" << '\n';
    Son *son = new Son;
    delete son;
    cout << "================" << '\n';

    return 0;
};

 

返回值:

  

GraphFather structure
Father structure
Son structure
GraphFather deconstruction  -----》 看这里
================
GraphFather structure
Father structure
Son structure
Father deconstruction  ------看这里
GraphFather deconstruction
================
GraphFather structure
Father structure
Son structure
Son Deconstruction  -------看这里
Father deconstruction
GraphFather deconstruction
================

 

这样只是理解了执行顺序, 但网友的那篇blog却讲的很好, 记录只是为了更好的理解和回顾

更好的理解virtual的作用, 和使用场景

 

#include <iostream>

using namespace std;

class Base
{
public:
    Base(){}
    ~Base()
    {
        cout << "Base Destructor." << endl;
    }
private:
    int a, b;
};

class Derive : public Base
{
public:
    Derive(){}
    ~Derive()
    {
        cout << "Derive Destructor." << endl;
        // release memeory
        if(pI != NULL)
        {
            delete pI;
        }
    }
private:
    int *pI;
};

int main(void)
{
    {
        Base *pD = new Derive;
        delete pD;
    }
    int i;
    cin >> i;

    return 0;
}
View Code

 

但结果只执行了基类的析构函数, 在派生类中有没有释放的指针, 这样就造成了内存泄漏

这也是虚析构函数的一个作用

在基类Base中加入虚析构函数virtual ~Base()...

#include <iostream>

using namespace std;

class Base {
public:
    Base() {}

    virtual ~Base() {
        cout << "Base Destructor." << endl;
    }

private:
    int a, b;
};

class Derive : public Base {
public:
    Derive() {
        pI = new int;
    }

    ~Derive() {
        cout << "Derive Destructor." << endl;
        // release memeory
        if (pI != NULL) {
            delete pI;
        }
    }

private:
    int *pI;
};

int main(int argc, char const *argv[]) {
    {
        Base *pD = new Derive;
        delete pD;
    }
    int i;
    cin >> i;

    return 0;
}

 

参考blog1:https://www.cnblogs.com/lit10050528/p/3874703.html

参考blog2: http://www.cnblogs.com/cxq0017/p/6550125.html   --》这个blog代码没有delete 对象指针, 需注意

 

posted @ 2018-07-19 11:39  我当道士那儿些年  阅读(705)  评论(0编辑  收藏  举报