首页 文章

在c中的析构函数概念

提问于
浏览
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 回答

  • 2

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

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

    如果不这样做,则在执行 delete Ptr 时会出现未定义的行为 .

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

    这是常规对象销毁序列的一部分 . 当你销毁一个对象时,首先调用该对象类的析构函数,然后调用该对象的所有非静态类成员的析构函数(按照声明的相反顺序), then the destructors of all its base classes .

    因此,虚拟分派在此处正确执行(当然,如果您创建基类析构函数 virtual ),从某种意义上说,被调用的第一个析构函数是对象的实际运行时类型的析构函数( ClassB ) . 之后,将调用基类 ClassA 的析构函数以及正常销毁过程的一部分 .

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

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

  • 3

    因为你的Base类析构函数应该是 virtual .

  • 0

    这实际上是 undefined behavior 因为 ~ClassA() 不是 virtual ,所以任何事情都可能发生 .

    ClassA *Ptr = new ClassB;
    ///....
    delete Ptr;
    
  • 0

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

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

相关问题