多态调用3层析构函数

Calling 3 layers of destructors in polymorphism

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

对于 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;
}

非常感谢您的建议。

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

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

class C{
    int* cp;

public:

    C(){ cp = new int;} 

    virtual ~C(){
        delete cp;
        cout << "~C()" << endl;
    }

    virtual void someMethod()=0;
};

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

class B: public C{
    int* bp;
    public:

    B(){ bp = new int;} 

    virtual ~B(){
        delete bp;
        cout << "~B()" << endl;
    }

    virtual void someMethod(){//some Implementation
    }
};

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

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

构造此 class 并使用 delete 调用析构函数将正确调用所有三个析构函数:

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

输出:

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

Try it online

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

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

class C{
    virtual ~C() = 0;
};

C::~C(){ /*Implementation here*/}

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