3

对于以下问题,我无法跳出框框思考。我有一个类层次结构:

[BaseClass] --> [Win32Class]

[BaseClass] --> [LinuxClass]

[BaseClass] --> [VxWorksClass]

实现类将调用 API 级函数。这些是在基类的纯虚函数中完成的。

现在,当用户创建、使用并完成对象时,他应该调用该Done函数(来自基类),该函数将进行清理和资源释放。这种清理工作的一部分是调用一些 API 级函数——这些自然是基类中的纯虚函数,并在派生类中实现。到目前为止,一切都很好。

这就是问题所在。如果用户没有显式调用Done,则会由于资源没有被正确释放而导致各种内存泄漏。所以,我想我会让它变得简单并调用- 破坏时自动清理,我想Done~BaseClass()好吧,没有那么多。由于Done对这些纯虚拟的调用,所有地狱都崩溃了。

关于如何重新设计它以避免这个问题的任何想法?

示例代码

class BaseClass{ 
  virtual ~BaseClass(){
    Done();
  }
  void Done(){
    // A bunch of OS-independent clean-up logic
    Cleanup();
    // some more OS-independent clean-up logic
  }
  virtual void Cleanup() = 0;
};
class Win32Class : public BaseClass{
  virtual void Cleanup(){
    // call some Win32-specific cleanup code
  }
};
class LinuxClass : public BaseClass{
  virtual void Cleanup(){
    // call some Linux-specific cleanup code
  }
};

===========================================
这是我的解决方案。使用包装类。不要调用orDone的析构函数Win32ClassBaseClass

class Win32Wrapper{
public:
  Win32Class* object_;
public:
  Win32Wrapper(){
    this->object_ = new Win32Class;
  }
  ~Win32Wrapper(){
    this->object_->Done();
    delete this->object_;
  }
};

== 如何在析构函数中调用 Pure Virtuals ==

class Base{
public:
  Base(){
  }
  virtual ~Base(){
    Done();
  }
  void Done(){
    Clean();
  }
  virtual void Clean() = 0;
};

class Derived : public Base{
public:  
  Derived(){
  }
  ~Derived(){
  }
  virtual void Clean(){
  }
};

用户认为该程序可以运行,因为编译器不会抱怨对 PFV in 的调用Base::Done()

4

3 回答 3

2

您可以将清理代码放在派生的析构函数中:

struct Base
{
    virtual ~Base() { }

    void CleanUp() { /* ... */ }
};

struct Derived : Base
{
    virtual ~Derived()
    {
        CleanUp();
    }
};

如果您愿意,您甚至可以将对更多虚拟函数的调用放入非虚拟Base::CleanUp()函数中,以允许特定于派生的行为(尽管根据您的描述,听起来您不需要那样)。

于 2012-11-06T23:27:39.320 回答
0

我认为 RAII 成语是您正在寻找的。

你可以在这里找到一个相当全面的描述:http ://www.hackcraft.net/raii/

于 2012-11-06T23:39:03.907 回答
0

你有两个选择。

  1. 的用户BaseClass必须打电话Done(),任何由于不这样做而引起的错误都是他的责任。
  2. 每个派生类都会在其析构函数中执行任何需要的清理工作。他们可以BaseClass在清理中使用函数,这些BaseClass函数甚至可以调用被派生类覆盖的函数。
于 2012-11-07T21:25:22.320 回答