【问题标题】:Call Destructor of derived ClassObjects via BaseClass List通过基类列表调用派生类对象的析构函数
【发布时间】:2012-08-11 20:27:19
【问题描述】:

我让这个类来获取所有派生对象的列表

Register.h
-----------------
class Register {
...
public:

// static object list
static list<Register*> instances;

// default constructor for register object
Register::Register();

// virtual destructor to clean up with subobject destructor first
virtual Register::~Register();

// default methods for this class
static void Register::stop();

Register.cpp
-----------------
#include "Register.h"

// list with all object instances made by this programm
list<Register*> Register::instances;

// default destructor
Register::~Register() {
  list<Register*>::iterator p = find(instances.begin(), instances.end(), this);
  if (p != instances.end()) {
    instances.erase(p);
  }
}

// erase all instances clean up the dish
void Register::stop() {
  // last log message
  Log::write("register cleanup");
  // stops the logging object
  Log::stop();
  // clean up instances
  list<Register*>::iterator iter = instances.begin();
  list<Register*>::iterator end  = instances.end();
  while (iter != end) {
    cout<< endl << (*iter) -> typeName << endl;
    //delete *iter;
  }
  Register::instances.clear();
}

和派生类

File.h
-----------------
class File : public Register {
...
// default destructor
virtual File::~File(void);
...
}

File.cpp
-----------------
// default destructor
File::~File(void) {
  cout << "file destr";
  this -> deleteFile();
}

Log.h
-----------------
// this class implements a log handler
// (derived from register)
class Log : public File {

public:
  // singelton logging object
  static Log* log;

  // default destructor
  Log::~Log(void);

Log.cpp
-----------------
using namespace std;

// declare pointer for easy logging
Log* Log::log = NULL;

// default destructor
Log::~Log(void) {
cout << "log destr";
}

现在我想删除整个结构,只需删除列表和其中的对象..

我试过了

 Main.cpp
-----------------
 int main (int argc, char *argv[], char *envp[]) {

   Register::stop();

   return 1;
 }

但对象仍被实例化

我没有想法^^

请...

【问题讨论】:

    标签: c++ class derived virtual-destructor


    【解决方案1】:

    注册::instances.clear();

    这会清除指针列表,但不会对对象做任何事情。您需要在清除列表之前自行删除它们,例如像这样

    for (list<Register *>::iterator it = Register::instances.begin();
         it != Register::instances.end();
         ++it) {
        delete *it;
    }
    Register::instances.clear();
    

    【讨论】:

    • i apreciate.. 但随后 vs++ 抛出调试断言失败!表达式:列表迭代器不可递增.. :-(
    • @AlexTape:见list iterator remove。如果您的析构函数负责从列表中删除对象,则此操作会修改列表并使迭代器无效。
    • @AlexTape 我认为@Pete 是对的,Register 或其派生类之一(可能是Log)的析构函数修改了列表。基本上,你得到的断言没有其他解释。
    • 你的权利..我什么也没解决..即使我调用 delete *它也会再次抛出“表达式:列表迭代器不兼容”......
    • @AlexTape 试试while(instances.size() &gt; 0) delete *instances.begin();,它应该适用于这种情况。但是提到近循环,列表项在项目的析构函数中被删除。
    【解决方案2】:

    作为手动清除列表的替代方法,C++11 引入了与 STL 容器兼容的 std::unique_ptr 智能指针。

    static std::list<std::unique_ptr<Register>> instances;
    

    基本上会负责删除对象。

    【讨论】:

    • 我包含 但错误 C2065: 'unique_ptr' : undeclared identifier ??
    • @AlexTape:什么编译器版本? (我假设 C2065 错误指向 VisualStudio,但版本将确定它是否支持 C++11——只有 VS2010 及更高版本有 unique_ptr
    【解决方案3】:

    好的..我解决了..

    // clean up instances
    list<Register*>::iterator iter = instances.begin();
    list<Register*>::iterator end  = instances.end();
    
    while (iter != end) {
      iter = instances.erase(iter);
    }
    Register::instances.clear();
    

    【讨论】:

    • 如果您打算删除列表中的指针所指向的对象,那么您在这里没有这样做。
    • 实际上,现在clear() 什么都不做,你在while 循环中完成它的工作。 erase() 和其他函数都不会为您释放对象。其他两个答案的解决方案都应该有效。
    • for (list&lt;Register*&gt;::iterator iter = instances.begin(); iter != instances.end(); ++iter) delete *iter; instances.clear();
    猜你喜欢
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2010-12-24
    • 2014-08-08
    • 2015-07-18
    • 2016-07-19
    • 2011-03-16
    • 1970-01-01
    相关资源
    最近更新 更多