带有QObject的空模式

时间:2010-08-31 08:08:37

标签: qt null-pointer null-object-pattern

(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子类化?

3 个答案:

答案 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替代原则。