- 续isA:在函数传参时,可以使用子类对父类进行初始化,但是注意,子类中的一些父类不包含的数据成员和成员函数会丢失
- 虚析构函数注意只是为了解决利用派生类生成父类的实例,需要父类具有虚函数,否则将有内存泄漏!
虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。换句话说,普通的析构函数在析构IsA这种方式的对象时只能析构了父类对象而无法析构子类对象。
如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性。
所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。
抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。
注意,虚析构函数都是写再基类中的!
举个例子:
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明(以下来自http://blog.csdn.net/liliangshuai/article/details/40425279):
有下面的两个类:
代码:class ClxBase { public: ClxBase() {}; virtual ~ClxBase() {}; virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; }; }; class ClxDerived : public ClxBase { public: ClxDerived() {}; ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }; };
输出结果是:ClxBase *pTest = new ClxDerived; pTest->DoSomething(); delete pTest;
这个很简单,非常好理解。Do something in class ClxDerived! Output from the destructor of class ClxDerived!
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。Do something in class ClxDerived!
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
- 虚函数使用限制
普通函数不能是虚函数
不能修饰静态成员函数,因为成员函数实例相关,静态函数类相关。虚函数,是一种特殊的成员函数,用来实现运行时多态的。所以静态函数不可能是虚函数。
不能修饰内联函数,编译会通过,但是编译时会忽略内联函数,内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数。
不能修饰构造函数,同样是因为在编译时会进行构造函数,而动态多态不是
C++虚析构函数
最新推荐文章于 2024-07-17 17:09:24 发布