昨天笔试的时候碰到一个很有意思的题目,大体如下:
class Parent { public: Parent() { doit(); } ~Parent() { doit(); } virtual void doit() { cout << "I‘m Parent!" << endl; } }; class Child: public Parent { public: Child() { } ~Child() { } void doit() { Parent::doit(); cout << "I‘m Child!" << endl; } }; int main() { Parent *p_base = new Child(); p_base->doit(); delete p_base; return 0; }
以前在项目中并没有写过在构造函数中调用虚函数的情况,这一般也是不允许的,增加了代码的复杂度(参见Effective C++ 条款9)。这里谨记C++继承中构造、析构的顺序就不难写出答案:
I‘m Parent! I‘m Parent! I‘m Child! I‘m Parent!
但是我觉得题目应该可以出的更巧妙一些:
class Parent { public: Parent() { doit(); } ~Parent() { doit(); } virtual void doit() { cout << "I‘m Parent!" << endl; } }; class Child: public Parent { public: Child() { doit(); } ~Child() { doit(); } void doit() { Parent::doit(); cout << "I‘m Child!" << endl; } }; int main() { Parent *p_base = new Child(); p_base->doit(); delete p_base; return 0; }
如果你写下:
I‘m Parent! I‘m Parent! I‘m Child! I‘m Parent! I‘m Child! I‘m Parent! I‘m Child! I‘m Parent!
那么,恭喜你,你答错了。因为这个题目根本不会调用子类的析构函数,为啥?因为父类的析构函数是非虚函数,但是main函数中在释放的静态类型指向父类,所以它根本不调用子类的析构函数。这也是为什么在继承体系中一般都需将父类的析构函数设为虚函数(参见Effective C++ 条款7),否则有可能造成内存泄露。
正确答案是:
I‘m Parent! I‘m Parent! I‘m Child! I‘m Parent! I‘m Child! I‘m Parent! I‘m Child! I‘m Parent!
时间: 2024-10-14 15:52:20