1. 运行结果是什么?

father *pf = new father();
delete pf;
father *ps = new son();
delete ps;
son *ps1 = new son();
delete ps1;
son *pss = new sonson();
delete pss;
father *pss1 = new sonson();
delete pss1;

2. 运行结果

delete father()
delete father()
delete son()
delete father()
delete sonson()
delete son()
delete father()
delete father()

3. 解释与结论

virtual关键字在父类virtual关键字在子类已经说明virtual关键字在父类的情况能够正常地进行多态。因此这里仅把关注点放在virtual关键字在子类的情况。

由于析构函数与普通函数略有不同,把virtual关键字在子类的情况对析构函数再测一遍。结论与virtual关键字在子类类似。

id 指针名 指针的类型 实际的类型 运行结果 解释
1 pf father father delete father()
2 ps father son delete father() 实际调用的是指针的类型(father)的析构函数,说明没有多态
3 ps1 son son delete son()
delete father()
调用了~son(),~son()又调用了~father() ,由编译器完成。
4 pss son sonson delete sonson()
delete son()
delete father()
实际调用的是对象的类型(sonson)的函数,说明有多态的效果。~sonson()又调用了~son()以及~father(),由编译器完成。
5 pss1 father sonson delete father() 实际调用的是指针的类型(father)的析构函数,说明没有多态

结论:

  1. 结论与virtual关键字在子类类似,可以对照着看。

  2. 如果virtual只写在派生类的析构函数中,而没有写在基类中的析构函数中,则不会有多态的效果。有可能只析构基类部分而不析构派生类部分,造成内存泄漏。

  3. 如果在某一层的派生类中加了virtual标签,那么从这一层开始以后的每一层,这个函数都会有多态的效果。

4. 其它测试

virtual关键字在父类

virtual关键字在子类

间接调用虚函数

5. 完整代码

#include <iostream>
using namespace std;

class father
{
public:
  ~father()
  {
    cout<<"delete father()"<<endl;
  }
};

class son : public father
{
public:
  virtual ~son()
  {
    cout<<"delete son()"<<endl;
  }
};

class sonson : public son
{
public:
  ~sonson()
  {
    cout<<"delete sonson()"<<endl;
  }
};

int main()
{
  father *pf = new father();
  delete pf;
  father *ps = new son();
  delete ps;
  son *ps1 = new son();
  delete ps1;
  son *pss = new sonson();
  delete pss;
  father *pss1 = new sonson();
  delete pss1;
  return 0;
}

results matching ""

    No results matching ""