在多态性中调用3层析构函数

Calling 3 layers of destructors in polymorphism

本文关键字:3层 析构函数 调用 多态性      更新时间:2023-10-16

我真的陷入了这个问题。我有一个内存泄漏的应用程序。为了解决这个问题,我需要调用类的析构函数。

对于2层类,这个问题很简单,但在这种情况下,有3层类,我找不到任何方法来编译:

#include<iostream>
using namespace std;
/* *MUST* be an abstract class and contains data that must be freed */
class C { 
public:
  virtual ~C()=0;
};
/* Contains concrete methods and contains data that has to be freed */
class B:public C { 
public:
  virtual ~B();
};
/* contains no data, only methods nothing needs to be freed in here */
class A:public B {
public:
  ~A();
};
int main(){
  C *c = new A;
  return 0;
}

当我编译代码时,我得到错误:

martyn@Hades ~ $ gcc deleteme.cpp -std=c++11
/tmp/cc7nxaw5.o: In function `main':
deleteme.cpp:(.text+0x12): undefined reference to `operator new(unsigned int)'
/tmp/cc7nxaw5.o: In function `__static_initialization_and_destruction_0(int, int)':
deleteme.cpp:(.text+0x4b): undefined reference to `std::ios_base::Init::Init()'
deleteme.cpp:(.text+0x62): undefined reference to `std::ios_base::Init::~Init()'
/tmp/cc7nxaw5.o: In function `B::B()':
deleteme.cpp:(.text._ZN1BC2Ev[_ZN1BC5Ev]+0x16): undefined reference to `vtable for B'
/tmp/cc7nxaw5.o: In function `A::A()':
deleteme.cpp:(.text._ZN1AC2Ev[_ZN1AC5Ev]+0x16): undefined reference to `vtable for A'
/tmp/cc7nxaw5.o:(.rodata._ZTV1C[_ZTV1C]+0x8): undefined reference to `__cxa_pure_virtual'
/tmp/cc7nxaw5.o:(.rodata._ZTV1C[_ZTV1C]+0xc): undefined reference to `__cxa_pure_virtual'
/tmp/cc7nxaw5.o:(.rodata._ZTI1C[_ZTI1C]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
collect2: error: ld returned 1 exit status

有人能想出一种方法,我可以重写析构函数,这样a、B和C的析构函数都被调用吗?

我用这个把头发都扯掉了,任何帮助都将不胜感激。但是,我不能更改注释或继承层次结构中的要求,这样做需要重写整个应用程序。

非常感谢。

编辑:非常感谢您对以下问题的评论,对我有效的解决方案是:

#include<iostream>
using namespace std;
/* *MUST* be an abstract class and contains data that must be freed */
class C { 
public:
  virtual ~C()=0;
};
C::~C(){
  cout<<"destroying C"<<endl;
}
/* Contains concrete methods and contains data that have to be freed */
class B:public C { 
public:
  ~B();
};
B::~B(){
  cout<<"destroying B"<<endl;
}
/* contains no data, only methods nothing needs to be freed in here */
class A:public B {
public:
  ~A();
};
A::~A(){
  cout<<"destroying A"<<endl;
}
int main(){
  C *c = new A;
  delete c;
  return 0;
}

非常感谢你的建议。

这里的解决方案是在需要析构函数的类中实现析构函数,并让编译器处理其余的。

首先,C有一些数据需要释放,所以C得到了这样的析构函数:

class C{
    int* cp;
public:
    C(){ cp = new int;} 
    virtual ~C(){
        delete cp;
        cout << "~C()" << endl;
    }
    virtual void someMethod()=0;
};

类B应该实现纯虚拟函数,并且有需要释放的数据,所以:

class B: public C{
    int* bp;
    public:
    B(){ bp = new int;} 
    virtual ~B(){
        delete bp;
        cout << "~B()" << endl;
    }
    virtual void someMethod(){//some Implementation
    }
};

最后,类A只提供了一些方法,所以我们不需要析构函数。但我也会在这里包括一个演示:

class A: public B{
    public:
    virtual ~A(){
        cout << "~A()" << endl;
    }
};

构造这个类并用delete调用析构函数将正确地调用所有三个析构函数:

int main(){
    C *c = new A;
    delete c;
    return 0;
}

输出:

~A()
~B()
~C()

在线试用

请注意:在您发布的代码中,您似乎试图使用纯虚拟析构函数的声明来使类抽象。但是,如果你必须释放类中的资源,那么你需要使用另一个函数来实现这个目的,如果你没有一个纯虚拟函数的话。

编辑:
阅读这里可以了解到,为同一函数提供纯说明符和定义确实是有效的,这也适用于析构函数。所以你确实可以做到这一点:

class C{
    virtual ~C() = 0;
};
C::~C(){ /*Implementation here*/}

最后,只要至少有一个函数是纯虚拟的(=0),那么类就是抽象的。如果这是析构函数或其他函数,则无关紧要。但是,如果您的类需要释放资源,则需要为析构函数提供一个主体。