1

我正在尝试在 Qt 中编写一个运行相对良好的应用程序,直到我遇到了这个愚蠢的问题。我有一个Node类,它可以有一个指向Workplace类实例的指针。我还为该指针定义了 getter/setter 方法。像这样的东西:

class Node : public QGraphicsItem
{
    Q_DECLARE_TR_FUNCTIONS(Node)

public:
    Node(const QString &type, Project* nodeProject);
    ~Node();

    void setWorkplace(Workplace* workplace);
    void removeWorkplace();
    Workplace* usedWorkplace();

    (...)
private:    
    Workplace* myWorkplace;
}

因此,现在在我的代码中,我必须检查某个特定对象Node是否具有指向已Workplace定义对象的指针,以便对该信息进行一些操作。这就是我的做法:

Workplace* currentWorkplacePointer = qobject_cast<Workplace*>(node->usedWorkplace());
if(!currentWorkplacePointer){
     // no workplace, do some stuff
}else{
     // workplace exists, do other stuff
}

这工作得很好,但现在由于某种原因它随机分段故障。我说随机是因为有时,如果我尝试清理和重建项目,它会正常工作 - 即,qobject_cast失败会静默失败并按我的预期进行;其他时候,即使我清理/重建,它也会再次出现段错误。

调试器控制台始终指向我上面代码中的对象转换行。据我所知,如果投射的对象不存在,投射不应该只是默默地失败吗?

请注意,我对 Qt/C++ 还很陌生,因此感谢您提供任何帮助和意见 - 请保持温和!:) 提前致谢!

4

2 回答 2

1

正如 Sebastian Redl 所说,将指针类型转换为自身类型似乎是无稽之谈。不过,您的代码可以改进,以供将来使用强制转换。我的第一点来自qobject_cast的文档,该文档强制在您的类头中调用Q_OBJECT宏以使其可用。

其次,作为您的Node继承QGraphicsItem,我建议qgraphicsitem_cast 改用它,它在处理或过滤场景中存在的项目时以不同的方式更快。改编自文档

 class Node : public QGraphicsItem
 {
    ...
    enum { Type = UserType + 1 };

    int type() const
    {
        // Enable the use of qgraphicsitem_cast with this item.
        return Type;
    }
    ...
 }

//in your application code
Node *n = qgraphicsitem_cast<Node*>(expected_pointer_on_node);
if (n) {
//then n points a Node
}
于 2013-09-10T22:58:58.803 回答
0

这实际上比我想象的要简单得多,而且我的问题实际上与该node->usedWorkplace()方法无法返回任何东西的事实有关,因为Workplace*在我尝试获取它之前没有初始化。笨蛋,我知道...

因此,我只是将指针初始化为0(谢谢,@ratchetfreak),然后从那里开始工作。现在一切正常。

因此,当我创建的实例时,我以这种方式Node初始化指针:0

nodeToPlace->setWorkplace(0);

然后,当我想检查Workplace*一个Node实例是否存在时:

Workplace* tempWorkplace = node->usedWorkplace();
if(!tempWorkplace){
     // do stuff
}else{
     // other stuff
}

所以我实际上根本不需要qobject_cast

注意:这最终没有涉及/回答我关于qobject_cast默默失败的问题。我最终发现的是,如果它失败或者你尝试投入某些东西,cast它将返回。我认为在我的初始代码中,后者正在发生。00

来自IBM Linux Compilers 文档dynamic_cast(根据 Qt 的文档向 C++ 报告大致等效):

表达式 dynamic_cast(v) 将表达式 v 转换为类型 T。类型 T 必须是指向完整类类型的指针或引用或指向 void 的指针。如果 T 是指针且 dynamic_cast 运算符失败,则运算符返回 T 类型的空指针。如果 T 是引用且 dynamic_cast 运算符失败,则运算符抛出异常 std::bad_cast。

因此,我会得出结论,我将垃圾称为演员的 arg,这使我的应用程序段错误(正如评论中提到的@hyde,因此我也对他 +1)。

如果有人有不同的意见和/或解释,请告诉我 - 我想了解更多关于我的错误/错误的信息。

于 2013-09-11T07:55:32.530 回答