虚拟析构函数和虚拟普通函数

    技术2022-05-12  5

    通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。否则其删除效果将无法实现。

    一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,从而千万内存泄漏。请看以下代码:

    #include "iostream.h" class A { public: A() { cout<<" A类的构造函数被调用"<<endl; } virtual ~A() { cout<<" A类的析构函数被调用"<<endl; } }; class B:public A { public: B() { cout<<" B类的构造函数被调用"<<endl; } ~B() { cout<<" B类的析构函数被调用"<<endl; } }; void main() { A* a=new B; //只有公有继承才允许这样 delete a; } /*如果基类A的析构函数不是虚拟的,那么派生类B的析构函数将不会被调用 输出为: A类的构造函数被调用 B类的构造函数被调用 A类的析构函数被调用 否则输出为: A类的构造函数被调用 B类的构造函数被调用 B类的析构函数被调用 A类的析构函数被调用 这就是为什么我们要在基类中使用虚拟析构函数的原因了*/

     

    下面再看一下不是析构函数的虚拟函数,这种函数设置为虚拟的目的是让基类提供一种方法,在子类中

    能够按照各自的需要来覆盖该方法,从而达到多态的目的。看下面的代码:

    #include "iostream.h" class A { public: A() { } virtual ~A() { } virtual void print() { cout<<"A类的print()被调用"<<endl; } }; class B:public A { public: B() { } ~B() { } void print() { cout<<"B类的print()被调用"<<endl; } }; void main() { B* b=new B; b->print(); A* a=new B; a->print(); } /*基类A的print函数没有设置为虚拟的情况下,调用哪个类的print函数是由指向对象的指针决定的,即等号左边的指针是属于哪个类的就调用哪个类的函数。否则是由对象本身决定的,即等号右边new后面是哪个类就调用哪个类的函数。 在没有virtual时输出为: B类的print()被调用 A类的print()被调用 在有virtual时输出为: B类的print()被调用 B类的print()被调用 如果是引用的话,如: void main() { B b; B* b1=&b; b1->print(); A* a=&b; a->print(); } 结果是一样的。 注意只有是指向类对象的指针或引用调用虚函数时才能起作用。*/


    最新回复(0)