1.析够函数和虚函数
析够函数:用来释放所定义对象使用的指针。
虚函数virtual:用基类指针指向不同派生类对象时,基类指针调用其成员函数,会调用真正指向派生类的的成员函数而不会调用基类的成员函数。若不是虚函数,不管基类指针指向哪个派生类,都会调用基类成员函数。
虚函数在成员函数中的使用
#include <iostream> using namespace std; class A{ public: A(){}; virtual ~A(){cout<<"~A class out"<<endl;} virtual void Dosomething(){cout<<"Do something in class A"<<endl;}; }; class B:public A{ public: B(){}; ~B(){cout<<"~B class out"<<endl;}; void Dosomething(){cout<<"Do something in class B"<<endl;}; }; int main(void) { A *ptest=new B; ptest->Dosomething(); delete ptest; return 0; }
基类A和派生类B都有相同的成员函数voidDosomething(){};,基类是虚函数,所以结果为
Dosomething in class B
~Bclass out
~Aclass out
如果去掉A中的virtual,结果为
Dosomething in class A
~Bclass out
~Aclass out
2.虚析够函数
自动调用基类部分的析构函数对基类的设计有重要影响。 删除指向动态分配对象的指针时,需要运行析构函数在释放对象的内存之前清除对象。处理继承层次中的对象时(如下),指针的静态类型可能与被删除对象的动态类型不同, 可能会删除实际指向派生类对象的基类类型指针 这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象 。 如果删除基类指针,则需要运行基类析构函数并清除基类的成员,如果对象实际是派生类型的,则没有定义该行为,要保证运行适当的析构函数,基类中的析构函数必须是析构的。 例如: class A; class B :public A 则 A* p = new B(), 是可以编译通过的,但在调用析构时需要调用B的析构函数,所以A必须定义为虚函数才能正确析构 通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。否则其删除效果将无法实现。 一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,从而千万内存泄漏 上面的代码如果不删除基类A的析够函数前的virtual,结果为 Do something in class B ~B class out ~A class out 如果删除virtual,派生类B的析够函数就调用不到 Do something in class B ~A class out