精华内容
下载资源
问答
  • C++ 虚析构函数
    2020-09-04 23:35:43

    上节我们讲到,构造函数不能是虚函数,因为派生类不能继承基类的构造函数,将构造函数声明为虚函数没有意义。

    这是原因之一,另外还有一个原因:C++ 中的构造函数用于在创建对象时进行初始化工作,在执行构造函数之前对象尚未创建完成,虚函数表尚不存在,也没有指向虚函数表的指针,所以此时无法查询虚函数表,也就不知道要调用哪一个构造函数。下节将会讲解虚函数表的概念。

    析构函数用于在销毁对象时进行清理工作,可以声明为虚函数,而且有时候必须要声明为虚函数。

    为了说明虚析构函数的必要性,请大家先看下面一个例子:

    #include <iostream>
    using namespace std;
    
    //基类
    class Base{
    public:
        Base();
        ~Base();
    protected:
        char *str;
    };
    Base::Base(){
        str = new char[100];
        cout<<"Base constructor"<<endl;
    }
    Base::~Base(){
        delete[] str;
        cout<<"Base destructor"<<endl;
    }
    
    //派生类
    class Derived: public Base{
    public:
        Derived();
        ~Derived();
    private:
        char *name;
    };
    Derived::Derived(){
        name = new char[100];
        cout<<"Derived constructor"<<endl;
    }
    Derived::~Derived(){
        delete[] name;
        cout<<"Derived de
    更多相关内容
  •  虚析构函数  析构函数的工作方式是:底层的派生类(most derived class)的析构函数先被调用,然后调用每一个基类的析构函数。  因为在C++中,当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非...
  • C++中,不能声明虚构造函数,但可以声明虚析构函数。多态性是指不同的对象对同一消息有不同的行为特性。虚函数作为运行时多态性的基础,主要是针对对象的,而构造函数是在对象产生之前运行的,因此虚构造函数是没有...
  • 主要介绍了C++虚析构函数的作用及其原理分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • C++虚析构函数

    2022-05-08 15:58:09
    为什么需要将基类析构函数设置为函数 我们来观察下面这段代码的表现: class Occupation { public: Occupation(){ std::cout << "Occupation()" << std::endl; }; ~Occupation(){ std::cout <<...

    为什么需要将基类析构函数设置为虚函数

    我们来观察下面这段代码的表现:

    class Occupation
    {
    public:
    	Occupation(){ std::cout << "Occupation()" << std::endl; };
        ~Occupation(){ std::cout << "~Occupation()" << std::endl; };
    	void show() { std::cout << "Occupation::show()" << std::endl; }
    };
    
    class Student : public Occupation
    {
    public:
    	Student(){ std::cout << "Student()" << std::endl; };
        ~Student(){ std::cout << "~Student()" << std::endl; };
    };
    
    int main()
    {
        Occupation * p = new Student();
        delete p;
        return 0;
    }
    

    编译运行后输出:

    Occupation()
    Student()
    ~Occupation()
    

    我们不难发现,派生类对象的析构函数没有被调用,也就是说,派生类对象的资源被泄露。

    原因

    Occupation * p = new Student();
    delete p;
    

    由于基类中析构函数v原始股虚函数,那么这里发生的是静态绑定,也就是说*p的类型是Occupation,所以,当进行delete时,只能调用Occupation类型的析构函数,而不会去调用派生类Student的析构函数。

    解决

    将基类的析构函数变成虚函数。

    class Occupation
    {
    public:
    	Occupation(){ std::cout << "Occupation()" << std::endl; };
        virtual ~Occupation(){ std::cout << "~Occupation()" << std::endl; };
    	void show() { std::cout << "Occupation::show()" << std::endl; }
    };
    

    编译运行输出:

    Occupation()
    Student()
    ~Student()
    ~Occupation()
    

    当基类的析构函数为虚函数时,派生类的析构函数自动转换成虚函数,而且此时发生的是动态绑定

    基类的虚函数表中存在&Occupation::~Occupation,派生类的虚函数表中继承来基类虚函数表中的内容,由于派生类的析构函数自动转换成了虚函数,那么派生类的析构函数覆盖掉虚函数表中基类的构造函数,此时派生类的虚函数表中存在的虚函数是:&Student ::~Student

    Occupation * p = new Student();
    delete p;
    

    delete p时,由于基类的析构函数是个虚函数,将进行访问RTTI,进行动态绑定,*p指的是Student类对象,那么Student类对象中的RTTI自然也是Student,那么将调用Student类的析构函数,完成派生类资源的释放,并且顺带调用基类析构,释放基类资源

    补充

    指针p一定是指向派生类堆上new出来的对象,栈上的不会发生资源泄露的问题 !!!! 解决该问题需要发生动态绑定。

    展开全文
  • C++虚析构函数和纯虚析构函数

    千次阅读 2020-07-05 10:31:05
    1、为什么要使用虚析构函数 我们知道析构函数是在对象生命周期结束时自动被调用,用来做一些清理工作(如释放句柄,释放堆内存等),防止出现内存泄漏。 那怎么还有虚析构函数呢? 使用虚析构函数的类一般是要...

    1、为什么要使用虚析构函数

    我们知道析构函数是在对象生命周期结束时自动被调用,用来做一些清理工作(如释放句柄,释放堆内存等),防止出现内存泄漏。

    那怎么还有虚析构函数呢?

    使用虚析构函数的类一般是要作为基类,被其他类继承。通过把基类的析构函数声明为虚函数,就可以通过父类指针来释放子类对象,从而完成子类的一些清理工作,防止出现内存泄漏。

    案例1:基类析构函数为非虚函数

    //test.h
    class Parent
    {
    public:
            Parent();
            ~Parent();
    private:
            int *p_ptr;
    };
    
    class Child : public Parent
    {
    public:
            Child();
            ~Child();
    private:
            int *c_ptr;
    };
    
    //test.cpp
    #include "test.h"
    #include <iostream>
    
    using namespace std;
    
    Parent::Parent()
    {
            p_ptr=new int;
            *p_ptr=10;
    }
    
    Parent::~Parent()
    {
            cout << "Parent::~Parent() was called." << endl;
            if(p_ptr != 0)
            {
                    delete p_ptr;
                    p_ptr=0;
            }
    }
    
    Child::Child()
    {
            c_ptr=new int;
            *c_ptr=20;
    }
    
    //main.cpp
    #include "test.h"
    
    void func(Parent *parent)
    {
            delete parent;//通过父类指针来释放子类对象
    }
    
    int main(int argc, char *argv[])
    {
            Child *child=new Child;
    
            func(child);
            return 1;
    }
    

    运行结果:

    Parent::~Parent() was called.
    结论:父类析构函数为非虚函数时,通过父类指针来释放子类对象时,只会调用父类的析构函数,而不会调用子类的析构函数,造成了子类的内存泄漏。所以,应该将父类的析构函数声明为虚函数。

    案例2:父类的析构函数为虚函数

    其他文件不用动,只需修改test.h,将父类的析构函数声明为虚函数。

    //test.h
    class Parent
    {
    public:
            Parent();
            virtual ~Parent();//虚析构函数
    private:
            int *p_ptr;
    };
    
    class Child : public Parent
    {
    public:
            Child();
            ~Child();
    private:
            int *c_ptr;
    };
    
    

    运行结果:

    Child::~Child() was called.
    Parent::~Parent() was called.
    结论:只有将父类的析构函数声明为虚析构函数时,通过父类指针释放子类对象时,会先调用子类的析构函数,然后调用父类的析构函数,不存在内存泄漏问题。

    2、纯虚析构函数

    通过上面的虚析构函数知道,C++基类的析构函数最好声明为虚机构函数,那什么时候声明为纯虚析构函数呢?

    我们知道,带有纯虚函数的类为抽象类,不能被实例化,只能被子类继承,所以当我们设计一个基类为抽象类时,可以把析构函数声明为纯虚析构函数,这样基类就是抽象类了。

    注意:纯虚析构函数也要有函数体,用来做一些基类的清理工作,防止基类出现内存泄漏。

    展开全文
  • C++ 虚析构函数作用

    2019-11-30 23:27:28
    那么虚析构函数的作用:就是释放派生类的内存,防止内存泄漏。 实例: 第一种情况,当没有虚析构函数时: // VirtualDemo.cpp : 定义控制台应用程序的入口点。 // 虚析构函数使用 #include "stdafx.h" #include &...
    • 简单的来说,虚函数的作用是当基类调用派生类的对象时,能够实现多态,即虚函数会优先调用派生类的对应函数。
    • 那么虚析构函数的作用:就是释放派生类的内存,防止内存泄漏。
      实例:
    • 第一种情况,当没有虚析构函数时:
    // VirtualDemo.cpp : 定义控制台应用程序的入口点。
    // 虚析构函数使用
    
    #include "stdafx.h"
    #include <memory>
    #include <iostream>
    using namespace std;
    
    class A{
    public:
    	A(){
    		cout << "A Init()" << endl;
    	}
        ~A(){
    		cout << "A Destroy()" << endl;
    	}
    };
    
    class B:public A{
    public:
    	B(){
    		cout << "B init()" << endl;
    	}
    	~B(){
    		cout << "B destroy()" << endl;
    	}
    };
    
    void test()
    {
    	unique_ptr<A> demo(new B());
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test();
    	system("pause");
    	return 0;
    }
    
    
    

    运行结果:
    在这里插入图片描述
    可以发现,只释放了A的内存,B的析构函数没有被调用

    • 接下来是添加虚析构函数的代码
    // VirtualDemo.cpp : 定义控制台应用程序的入口点。
    // 虚析构函数使用
    
    #include "stdafx.h"
    #include <memory>
    #include <iostream>
    using namespace std;
    
    class A{
    public:
    	A(){
    		cout << "A Init()" << endl;
    	}
        virtual ~A(){
    		cout << "A Destroy()" << endl;
    	}
    };
    
    class B:public A{
    public:
    	B(){
    		cout << "B init()" << endl;
    	}
    	~B(){
    		cout << "B destroy()" << endl;
    	}
    };
    
    void test()
    {
    	unique_ptr<A> demo(new B());
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test();
    	system("pause");
    	return 0;
    }
    
    
    

    运行结果:
    在这里插入图片描述
    可以看出,此时B的析构函数也被调用,至于为什么也被调用,那就是虚函数表的作用,这个和虚函数的原理是一摸一样的,在此,不继续赘述了。能明白就还好~


    重点:
    只针对需要作为基类的包含虚函数的类才添加虚析构函数,其他的东西 添加纯属扯淡。

    虚函数表在编译的时候就确定了,而类对象的虚函数指针vptr是在运行阶段确定的,这是实现多态的关键!

    展开全文
  • c++虚析构函数的作用

    2018-05-13 12:11:36
    转自:https://blog.csdn.net/derkampf/article/details/62093252C++中的虚析构函数到底什么时候有用的,什么作用呢。 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员...
  • c++ virtual 虚析构函数及虚函数的详细例子.rar
  • 我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是函数。 可是,为什么要这样做呢?下面用一个小例子来说明: 1#include<iostream> 2 using namespace std; 3 class Base 4 { 5 public:...
  • C++ 虚析构函数与析构函数的区别

    千次阅读 2018-10-09 11:34:14
    换句话说当加了virtual 后,就会先执行子类的析构函数,再执行基类的析构函数。 2、不执行析构函数,就可能会存在内存泄露。 很明显,不加virtual的情况下,子类的析构函数没有执行。 那什么情况下用virtual析构...
  • C++虚析构函数及delete操作分析

    千次阅读 2020-10-30 12:22:44
    通常我们在写一个基类的时候,若基类成员变量需要动态申请内存空间或基类成员变量引用了系统资源时,需定义类的析构函数来明确在删除对象时需要释放的成员。 1. 析构函数 析构函数在析构时调用。若在堆上申请的内存...
  • C++静态关联与动态关联、C++是怎样实现多态性的 在现实生活中,多态性的例子是很多的。我们分析一下人是怎样处理多 态性的。例如,新生被录取人大学,在人学报到时,先有一名工作人员审查材料,他的职责是甄别资格,...
  • C++虚函数全面解析虚函数的工作原理:虚析构函数:C++中的静态联编和动态联编 学习过C++的都知道可以通过虚函数实现多态。在基类中定义一个虚函数,在派生类中可以重写这个虚函数,实现派生类自己的特性。 虚函数的...
  • C++虚析构函数的必要性 C++程序员经常会面对的问题就是内存泄漏,如果操作不当发生内存泄漏,那么将会是毁灭性的Bug。在继承里,大部分基类中的析构函数通常会声明为虚函数,这样会避免指针占用的堆内存得不到释放...
  • 虚析构函数有啥用? 先测测你哟,上代码????: #include<iostream> using namespace std; class Base //父类(基类) { public: Base() { cout << "Base构造函数!" << endl; } ~Base() { ...
  • 虚析构函数的作用: 析构函数是可以声明为虚函数的,如果基类指针指向一个new生成的派生类对象,通过delete作用于基类指针删除派生类对象时,有...所以C++中的析构函数通常是虚析构函数虚析构函数的声明语法: .
  • 本篇文章是对C++虚析构函数的作用进行了详细的分析介绍,需要的朋友参考下
  • C++析构函数 (1)对于析构函数析构函数与构造函数相呼应,从调用构造函数开始到自动执行析构函数二者调用期间即为所创建对象实例的生命周期。 (2)析构函数与类名相同,仅前面加一个~,一般析构函数无参,且无...
  • 如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的...
  • 虚析构函数 为了能够正确的调用对象的析构函数,一般要求具有层次结构的顶级类定义其析构函数为虚函数。因为在delete一个抽象类指针时候,必须要通过虚函数找到真正的析构函数。 class Base { public: Base(){} ...
  • C++ 虚拟析构函数 (virtual destructor)

    千次阅读 多人点赞 2021-05-15 07:19:47
    C++ 虚拟析构函数 (virtual destructor). 虚拟析构函数的用法以及使用场景.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 46,866
精华内容 18,746
关键字:

C++ 虚析构函数