zoukankan      html  css  js  c++  java
  • C++ 虚析构函数

    联编就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址,它是计算机程序彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。

    静态联编是指在编译阶段就将函数实现和函数调用关联起来,因此静态联编也叫早绑定,在编译阶段就必须了解所有的函数或模块执行所需要检测的信息,它对函数的选择是基于指向对象的指针(或者引用)的类型,C语言中,所有的联编都是静态联编,据我所知道的,任何一种编译器都支持静态联编(废话)。

    动态联编是指在程序执行的时候才将函数实现和函数调用关联,因此也叫运行时绑定或者晚绑定,动态联编对函数的选择不是基于指针或者引用,而是基于对象类型,不同的对象类型将做出不同的编译结果。C++中一般情况下联编也是静态联编,但是一旦涉及到多态和虚拟函数就必须要使用动态联编了。

    以上内容引用自http://blog.csdn.net/blucexi/article/details/1253265

    请看下面的程序:

    #include <iostream>  
    using namespace std;  
     
    class A
    {
    public:
    	A()
    	{
    		cout<<"new a A"<<endl;
    	}
    	~A()
    	{
    		cout<<"delete a A"<<endl;
    	}  
    };
    
    class B : public A
    {
    public:
    	B()
    	{
    		cout<<"new a B"<<endl;
    	}
    	~B()
    	{
    		cout<<"delete a B"<<endl;
    	} 
    };
    
    void test1()
    {
        B b;
    }
    
    void test2()
    {
    	A *pA;
    	pA = new B(); 
    	delete pA;
    }
    
    int main()
    {  
    	test1();
    	test2();
    	system("pause");
    	return 0;
    }
    

    test2函数执行后不会调用B类的析构函数。因为,A类和B类的析构函数都是静态联编的,即编译时就根据对象或指针的类型确定其在被销毁时将要调用的析构函数。则自然test2函数中唯一的变量pA在test2函数执行完后调用A类的析构函数,而在test2函数执行过程之中new出来的B类的一个对象,没有被销毁。这将导致内存泄露。那么怎样才能防止这类内存泄露,让test2执行完后也调用B类的析构函数呢?
    这时候就需要用到动态联编了,也就是要用到虚函数。虚函数则是在程序运行时,根据其对象类型来调用相应的函数。请看下面的程序:

    #include <iostream>  
    using namespace std;  
     
    class A
    {
    public:
    	A()
    	{
    		cout<<"new a A"<<endl;
    	}
    	virtual ~A()
    	{
    		cout<<"delete a A"<<endl;
    	}  
    };
    
    class B : public A
    {
    public:
    	B()
    	{
    		cout<<"new a B"<<endl;
    	}
    	virtual ~B()
    	{
    		cout<<"delete a B"<<endl;
    	} 
    };
    
    void test1()
    {
        B b;
    }
    
    void test2()
    {
    	A *pA;
    	pA = new B(); 
    	delete pA;
    }
    
    int main()
    {  
    	test1();
    	test2();
    	system("pause");
    	return 0;
    }
    

      

    上面程序的输出结果是:

    这说明,在test2执行后,delete pA时,是根据pA实际指向的对象来调用析构函数的,也就是调用B的析构函数。但是B是继承A的,故在调用B的析构函数后,会再去调用其父类即A类的析构函数。test1函数的执行过程充分说明了继承中构造函数和析构函数的调用顺序。这也恰好验证了test2函数中检验虚析构函数的功效。
    使用虚析构函数,及时释放资源,防止内存泄露。但是在没有涉及到多态的时候可以不使用虚析构函数,毕竟任何虚函数都是要以类维护一个VTable和VTable指针为代价的。

  • 相关阅读:
    MVC 使用Response.Redirect页面301重定向
    火狐浏览器缓存登录名、密码解决方法
    访问网站不存在的页面的时候跳转到指定页面,不需要报文件不存在
    2 分钟读懂大数据框架 Hadoop 和 Spark 的异同
    toString("#.##")
    状态保存机制之ViewState概述及应用
    数据库分页
    【模拟】 【HDU 5831】 Rikka with Parenthesis II
    【贪心】 【HDU 5821】 Ball
    【set】【HDU 5818】 Joint Stacks
  • 原文地址:https://www.cnblogs.com/luojinping/p/3283549.html
Copyright © 2011-2022 走看看