(C ++ / Qt)我有一个指向QObject的智能指针。让我们说一个QWeakPointer。由于某些外部原因(可能在另一个对象中或由于事件而发生的事情),指向的对象可能会被销毁。因为我有一个智能指针,所以没有悬空参考,所以没有问题。但我总是要检查指针是否为空。
我正在考虑使用null模式以避免一直检查这个,但我不确定这是否可能或方便使用QObject。我们的想法是指针指向对象,如果它被销毁,智能指针会将其指向的对象更改为空对象。这是一个好主意还是我应该忘记它并且只是检查指针是否一直是NULL?
让我们举个例子。我们有一个工人使用工具来完成它的工作:
class Worker : public QObject
{
Q_OBJECT
public:
Worker(QObject *parent = 0);
void work()
{
if(m_tool)
m_tool->use();
emit workCompleted();
};
signals:
workCompleted();
public slots:
void setTool(QWeakPointer<Tool> tool);
private:
QWeakPointer<Tool> m_tool;
};
class Tool : public QObject
{
Q_OBJECT
public:
Tool();
public slots:
void use() =0;
};
class Screwdriver : public Tool
{
Q_OBJECT
public:
Screwdriver() : Tool();
public slots:
void use()
{
// do something
};
};
class Hammer : public Tool;
class Saw : public Tool;
...
在这种情况下,Tool是库的公共域对象,由Worker使用。我正在开发这样的库。因此,工人正在使用螺丝刀,但它会被破坏并被破坏。没问题:
if(m_tool)
m_tool->use();
emit workCompleted();
m_tool为0所以它什么都不做。但我们必须检查它是否每次都不为空。
现在假设我们有一个NullTool对象:
class NullTool : public Tool
{
Q_OBJECT
public:
NullTool() : Tool();
public slots:
void use()
{
// does nothing
};
};
当工具被销毁时,我们的指针会很聪明,并且知道它应该指向NullTool实例。所以Worker :: work()可以像这样实现:
void Worker::work()
{
m_tool->use();
emit workCompleted();
};
m_tool-&gt;然后在NullTool上调用use(),它不执行任何操作,因此不需要检查指针是否为空。
这是个好主意吗?是否可以使用智能指针类Qt提供或者我应该将QWeakPointer子类化?
答案 0 :(得分:3)
我认为null对象模式对类似值的类最有意义。例如QString或QVariant,你不想拥有像if(str&amp;&amp;!str-&gt; isEmpty())这样的代码,但只需要if(!str.isEmpty())。对于QObjects,它不是值但具有“身份”,我从未发现它有用。
答案 1 :(得分:0)
我不清楚您的用例,但是当通过连接来自QObject的以下信号来破坏对象时,可以发信号通知您的程序:
void destroyed ( QObject * obj = 0 );
答案 2 :(得分:0)
我认为你的想法没有任何问题。您只需要比较实现它所需的工作与每次检查指针的工作。让我们检查指针10.000次使用你的方法是个好主意。 旁注:您的空对象模式依赖于Tool::use()
无任何副作用的事实。
请注意Tool::use()
中可能的副作用不会妨碍您使用NullTool::use()
多态替换它时。换句话说:确保你没有打破Liskov替代原则。