Нулевой шаблон с QObject - PullRequest
       20

Нулевой шаблон с QObject

3 голосов
/ 31 августа 2010

(C ++ / Qt) У меня есть умный указатель на QObject.Скажем, QWeakPointer.По некоторой внешней причине (что-то, что может произойти в другом объекте или из-за события), возможно, что указанный объект разрушен.Так как у меня есть умный указатель, не будет висящей ссылки, так что нет проблем.Но я всегда должен проверять, является ли указатель нулевым или нет.

Я думаю об использовании нулевого шаблона, чтобы не проверять его постоянно, но я не уверен, возможно ли это или удобнос 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;
...

В этом случае Инструмент является общедоступным объектом библиотеки, который используется Работником.Я занимаюсь разработкой такой библиотеки.Таким образом, рабочий использует отвертку, но она сломается и будет разрушена.Нет проблем:

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-> use () будет вызван для NullTool, который ничего не делает, поэтому нет необходимости проверять указательне нуль.

Это хорошая идея?Возможно ли использовать классы интеллектуальных указателей, предоставляемые Qt, или я должен создать подкласс QWeakPointer?

Ответы [ 3 ]

3 голосов
/ 31 августа 2010

Я думаю, что шаблон с нулевым объектом наиболее целесообразен для классов, подобных значениям.Примерами являются QString или QVariant, если вы не хотите иметь код, подобный if (str &&! Str-> isEmpty ()), а просто делаете if (! Str.isEmpty ()).Для объектов QObject, которые не являются значениями, но имеют «идентичность», я никогда не находил это полезным.

0 голосов
/ 05 сентября 2010

Я не вижу никаких проблем в вашей идее.Вам просто нужно сравнить работу, которая требуется для его реализации, с работой по проверке указателя каждый раз.Давайте проверим указатель 10.000 раз - это хорошая идея, чтобы использовать ваш подход. Примечание: Ваш шаблон нулевого объекта основан на том факте, что Tool::use() не имеет никаких побочных эффектов.

Позаботьтесь о том, чтобы возможные побочные эффекты в Tool::use() не мешаликогда вы заменяете его полиморфно на NullTool::use().Другими словами: убедитесь, что вы не нарушаете принцип подстановки Лискова.

0 голосов
/ 31 августа 2010

Я не совсем понимаю ваш вариант использования, но ваша программа может получить сигнал, когда объект был уничтожен, подключив следующий сигнал из QObject:

void destroyed ( QObject * obj = 0 );
...