0

请通过我的以下代码:

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;

class ClassA
{
    protected:
    int width, height;

    public:
  void set_values(int x, int y)
  {
      width = x;
      height = y;
  }
  virtual int area()
  {
      return 100;
  }
  ~ClassA()
  {
      cout << "base class destructor called" << endl;

  }
};

class ClassB : public ClassA
{
    public :
int area()
{
    return (width * height);
}
~ClassB()
{
    cout << "derived class destructor called" << endl;
}
};
int main()
{
  ClassA *Ptr = new ClassB;
  Ptr->set_values(10, 20);
  cout << Ptr->area() << endl;
  delete Ptr;
     return 0;
} 

在上面的代码中,指针包含派生类对象的地址,所以当我删除指针时它应该调用派生类析构函数和基类析构函数,但为什么它只调用基类析构函数。如果我将基类析构函数设为虚拟,那么它同时调用派生类和基类析构函数,为什么?在虚函数的情况下,基类和派生类都具有相同的函数名称,因此编译器解析派生类中派生最多的函数名称,但这里的析构函数不会具有相同的名称,那么编译器如何解析它必须调用的函数名称在运行时。请解释我如何

4

4 回答 4

3

您应该制作基类的virtual析构函数以使多态破坏正常工作:

class ClassA
{
    // ...
    virtual ~ClassA()
//  ^^^^^^^
//  Add this!
    {
        cout << "base class destructor called" << endl;
    }
};

如果你不这样做,你在做的时候会得到未定义的行为delete Ptr

如果我将基类析构函数设为虚拟,那么它同时调用派生类和基类析构函数,为什么?

这是常规对象销毁序列的一部分。当您销毁一个对象时,首先调用该对象的类的析构函数,然后是该对象的所有非静态类成员的析构函数(按声明的相反顺序),然​​后是其所有基类的析构函数

因此,这里正确地执行了虚拟调度(当然,如果您创建了基类析构函数virtual),因为第一个被调用的析构函数是对象的实际运行时类型的析构函数(ClassB)。之后,基类的析构函数ClassA被调用,也是正常销毁过程的一部分。

但是这里的析构函数不会有相同的名称,那么编译器如何解析它在运行时必须调用的名称

析构函数是特殊的成员函数。每个类只能有一个析构函数,因此它们的名称(必须与类的名称相同,带有前置~字符)是无关紧要的。编译器知道哪个函数是析构函数。

于 2013-03-08T11:22:10.600 回答
2

因为您的基类析构函数应该是virtual.

于 2013-03-08T11:21:46.140 回答
0

这实际上是未定义的行为,因为~ClassA()is not virtual,所以任何事情都可能发生。

ClassA *Ptr = new ClassB;
///....
delete Ptr;
于 2013-03-08T11:21:39.647 回答
0

您需要将析构函数标记为虚拟的。否则编译器不知道调用最派生的析构函数。

virtual ~ClassA()
{
    cout << "base class destructor called" << endl;

}
于 2013-03-08T11:21:53.153 回答