首页 > 编程知识 正文

虚函数底层实现原理,函数库虚拟化的特点

时间:2023-05-05 15:14:19 阅读:27201 作者:1107

析构函数的析构函数的作用是在对象被取消之前进行必要的“现场清理”。 然而,如果从存储器中撤消派生类的对象,则通常先调用派生类的析构函数,然后调用基类的析构函数。 但是,如果使用new运算符创建临时对象,则在基类中存在析构函数,并且定义了指向该基类的指针变量,则程序在使用带有指针参数的delele运算符取消对象时,会出现基类的析构函数

以下示例显示由于析构函数调用不正确而导致的内存泄漏。

//析构函数调用不正确导致的内存泄漏。 cpp :定义控制台APP应用程序的入口点。 # include ' STD afx.h ' # includeiostreamusingnamespacestd; class base { private : char * data; //字符指针public:Base ()//无参数构造函数) {data=new char[64]; //动态内存申请cout 'Base类构造函数被调用的' endl; (; ~Base ()//析构函数({delete[] data; //data指向的内存释放并调用cout 'Base类析构函数的' endl; (; (; classchild :公共库{ private : char * m _ data; //字符指针public:child(:base )//派生类的构造函数,在初始化表中运行基类的构造函数(m_data=newchar(64 ); //进行动态内存申请,为m_datacout 'Child类构造函数分配起始地址' endl; (; (~Child ) )//析构函数) {delete[] m_data; //调用内存资源释放cout 'Child类析构函数的' endl; (; (; int main () {Base *pB=new Child; 运行基类析构函数return 0,动态申请分配给Base基类指针delete pB的Child大小的内存}

结果显示没有调用Child类的析构函数,而是Child类的char类型指针m_data指向的动态内存泄漏。

虚析构函数是为了解决这样的一个问题, 基类的指针指向派生类对象,并用基类的指针删除派生类对象。

析构函数的概念和用法很简单,但在面向对象编程中是一个重要的技巧。声明虚析构函数,即使基类并不需要析构函数,也显式地定义一个函数体为空的虚析构函数,以保证在撤销动态分配空间时能正确地处理。

如果将基类的析构函数声明为虚函数,则从基类派生的所有派生类的析构函数将自动成为虚函数,即使派生类的析构函数与基类的析构函数的名称不同。

析构函数名称和类名必须相同。 一般而言,如果某个类定义了虚函数,则析构函数也应该定义为虚析构。

在析构函数前加上关键字virual进行说明,该析构函数称为虚拟析构函数。

构造函数不能声明为虚函数,但析构函数可以声明为虚函数。

class类名{ virtual ~析构函数名(); (; 将基类析构函数定义为虚拟析构函数可以解决内存泄漏问题。

//虚拟析构函数解决内存泄漏问题。 cpp :定义控制台APP应用程序的入口点。 # include ' STD afx.h ' # includeiostreamusingnamespacestd; class base { private : char * data; //字符指针public:Base ()//无参数构造函数) {data=new char[64]; cout 'Base类构造函数为' endl; (; 虚拟到基本()//虚拟析构函数(delete ) )数据; 调用cout 'Base类析构函数的' endl; (; (; class child :公共库{ p

rivate:char* m_data; //字符指针public:Child() : Base() //无参构造函数{m_data = new char[64];cout << "Child类构造函数被调用" << endl;};~Child() //析构函数,继承虚拟virtual{delete[] m_data;cout << "Child类析构函数被调用" << endl;};};class GrandChild : public Child{private:char* mm_data; //字符指针public:GrandChild() //无参构造函数{mm_data = new char[64];cout << "GrandChild类构造函数被调用" << endl;};~GrandChild() //虚析构函数, virtual从继承结构中得来{delete[] mm_data;cout << "GrandChild类析构函数被调用" << endl;};};int main( ){Base *pB = new Child; // 动态申请了一块Child大小的内存,赋给Base基类指针delete pB; //Child类的析构函数执行,释放内存,不会泄露Child *pC = new GrandChild; // 动态申请了一块GrandChild大小的内存,赋给Child基类指针delete pC; //GrandChild类的析构函数执行,释放内存,不会泄露return 0;}

从结果可以看出,delete pB和delete pC很好地调用了类层次结构上的所有析构函数,避免了内存泄漏。

关键在于,在Base类中析构函数用virtual修饰,定义为了虚析构函数,这意味着从该基类的素有派生类的析构函数都继承为虚函数。

因此,Child和GrandChild类的析构函数,通过delete指针撤销指针所指的对象时,不再根据指针的类型,而是根据指针指向对象的类型来调用析构函数,很好地完成了内存清理的任务。

注意:虚析构函数的继承与普通虚函数的继承函数名不同,除了~外,析构函数和类同名,所以只要基类的析构函数定义为虚函数,派生类中的析构函数便继承为虚函数。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。