【发布时间】:2014-04-23 05:57:02
【问题描述】:
我有一个继承,基类的析构函数应用Template Method Pattern。析构函数在调用virtual clean函数之前要做一些工作,调用之后还要做一些工作。
我们知道Never Call Virtual Functions during Construction or Destruction。所以下面的代码肯定是不可用的。
class base
{
public:
virtual ~base()
{
// ... do something before do_clear()
do_clear();
// ... do something after do_clear()
}
private:
virtual void do_clear() = 0;
};
class d1
: public base
{
public:
d1() : m_x(new int) {}
~d1() {}
private:
virtual void do_clear()
{
delete m_x;
}
int *m_x;
};
但是如果我将进程的析构移到派生类的析构函数中,例如:
class base
{
public:
virtual ~base()
{
}
protected:
void clear()
{
// ... do something before do_clear()
do_clear();
// ... do something after do_clear()
}
private:
virtual void do_clear() = 0;
};
class d1
: public base
{
public:
d1() : m_x(new int) {}
~d1()
{
clear();
}
private:
virtual void do_clear()
{
delete m_x;
}
int *m_x;
};
如果客户这样写:
base *x = new d1;
delete x;
它会调用~d1(),然后调用base::clear(),最终正确调用虚函数d1::do_clear()。
base::clear() 可以公开,客户可以在销毁前调用base::clear() 安全地做事。前提是客户必须知道并且不要忘记调用,我认为这不方便并且破坏了封装。
我的问题是:
- 设计是否有危险/风险?
- 是否存在其他更好的设计?
【问题讨论】:
-
如果在销毁对象之前需要满足一些先决条件,我认为它应该是析构函数本身的一部分,这是一个好兆头。为什么不能在派生的析构函数中简单地
delete m_x? -
在析构函数、构造函数中搜索调用虚函数,应该能找到。
-
您在 (1) 的列表中遗漏了“/insidious”;一个形容词,用于描述您在从 Scott Meyers 链接的文章的第二个代码示例之后所建议的内容。您的派生类专门分配成员数据,然后依赖基类进行清理,这应该是一种邪恶的暗示。
标签: c++