QObject 的空模式
(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;
...
在本例中,工具是库的公共域对象,由工作人员使用。我正在开发这样的库。因此,工人正在使用螺丝刀,但它被损坏并被毁坏。没问题:
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();
};
然后在 NullTool 上调用 m_tool->use() ,它不执行任何操作,因此不需要检查指针是否为空。
这是个好主意吗?是否可以使用 Qt 提供的智能指针类,或者我应该子类化 QWeakPointer?
(C++/Qt) I have a smart pointer to a QObject. Let's say a QWeakPointer. For some external reason (something that might happen in another object or due to an event), it is possible that the pointed object gets destroyed. Since I have a smart pointer there will be no dangling reference, so there's no problem. But I always have to check if the pointer is null or not.
I'm thinking of using the null pattern in order to avoid checking this all the time but I'm not sure if this is possible or convenient with a QObject. The idea would be that the pointer points to the object and in case it gets destroyed, the smart pointer changes its pointed object to a null object. Is this a good idea or should I forget it and just check if the pointer is NULL all the time?
Let's show you an example. We have a worker who uses a tool to do its work:
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;
...
In this case, the Tool is a public domain object of a library, which is used by the Worker. I'm developing such library. So the worker is using a screwdriver but it gets broken and gets destroyed. No problem:
if(m_tool)
m_tool->use();
emit workCompleted();
m_tool is 0 so it simply does nothing. But we have to check that it's not null everytime.
Now let's say we had a NullTool object:
class NullTool : public Tool
{
Q_OBJECT
public:
NullTool() : Tool();
public slots:
void use()
{
// does nothing
};
};
When the tool was destroyed, our pointer would be smart and would know it should point to a NullTool instance. So Worker::work() could be implemented like this:
void Worker::work()
{
m_tool->use();
emit workCompleted();
};
m_tool->use() would then get called on the NullTool which does nothing, so there would be no need to check the pointer is not null.
Is this a good idea? Is it possible with the smart pointer classes Qt provides or should I subclass QWeakPointer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为空对象模式对于类似值的类最有意义。例如 QString 或 QVariant,如果您不想使用 if ( str && !str->isEmpty() ) 等代码,而只想使用 if ( !str.isEmpty() )。对于 QObjects,它们不是值,而是具有“身份”,我从来没有发现这有用。
I think the null object pattern makes most sense for value-like classes. Examples are QString or QVariant, were you don't want to have code like if ( str && !str->isEmpty() ) but just do if ( !str.isEmpty() ). For QObjects, which are not values but have "an identity", I never found this useful.
我不清楚你的用例,但是当对象被销毁时,你的程序可以通过从 QObject 连接以下信号来发出信号:
I don't understand clearly your use case, but your program can be signaled when the object has been destroy by connecting the following signal from QObject:
我不认为你的想法有任何问题。您只需将实现它所需的工作与每次检查指针的工作进行比较即可。让我们检查指针 10.000 次,使用您的方法是一个好主意。 附注:您的空对象模式依赖于
Tool::use()
没有任何副作用这一事实。请注意,当您用
NullTool::use()
多态地替换它时,Tool::use()
中可能存在的副作用不会妨碍它。换句话说:确保不违反里氏替换原则。I don't see any problem in your idea. You just have to compare the work that it takes to implement it compared to the work for checking the pointer every time. Let's your checking the pointer 10.000 times it's a good idea to use your approach. Side note: Your null object pattern rely on the fact that
Tool::use()
has no side effects whatsoever.Take care that possible side affects in
Tool::use()
don't get in the way when you replace it polymorphically withNullTool::use()
. In other words: Be sure you don't break the Liskov Substitution Principle.