简体   繁体   English

在这种情况下,qobject_cast是否应该默默失败?

[英]Shouldn't qobject_cast fail silently in this case?

I'm trying to code an application in Qt which was going relatively well until I bumped into this stupid problem. 我正在尝试用Qt编写一个应用程序,该应用程序运行得比较好,直到遇到这个愚蠢的问题。 I have a Node class which can have a pointer to a Workplace class instance. 我有一个Node类,它可以具有一个指向Workplace类实例的指针。 I have also defined getter/setter methods for that pointer. 我还为该指针定义了getter / setter方法。 Something like this: 像这样:

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;
}

So, now in my code, I have to check if a certain Node has a pointer to a Workplace defined, in order to do some operations with that info. 因此,现在在我的代码中,我必须检查某个Node是否具有指向定义的Workplace的指针,以便对该信息进行一些操作。 This is how I am doing it: 这就是我的做法:

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

This was working perfectly, but now for some reason it seg faults randomly . 这工作得很好,但是现在由于某种原因它会随机断断续续。 I say randomly because sometimes, if I try to clean and rebuild the project, it works correctly - ie, the qobject_cast fails silently and procedes as I intended; 我随便说qobject_cast ,因为有时,如果我尝试清理并重建项目,则它会正常工作-即, qobject_cast静默失败并按照我的预期进行; other times, even if I clean/rebuild, it seg-faults again. 其他时候,即使我清理/重建,它也会再次出现段错误。

The debugger console always points to the object cast line in my code above. 调试器控制台始终指向上面我的代码中的对象强制转换线。 To the best of my knowledge, shouldn't the cast simply fail silently if the casted object does not exist? 据我所知,如果不存在强制转换的对象,强制转换是否应该仅默默地失败?

Please note that I am very new to Qt/C++, so any help and comments are appreciated - just please be gentle! 请注意,我对Qt / C ++还是陌生的,因此,感谢您提供任何帮助和意见-请保持温柔! :) Thanks in advance! :) 提前致谢!

As well say by Sebastian Redl, it seem a nonsense to cast a pointer in itself type. 正如塞巴斯蒂安·雷德尔(Sebastian Redl)所说的那样,将指针转换为自身类型似乎是胡说八道。 Nevertheless, your code could be improve for future usage of casting. 不过,您的代码可能会有所改进,以便将来使用强制转换。 My first point come from documentation of qobject_cast that impose to call Q_OBJECT macro in your class header to be usable. 我的第一点来自qobject_cast的文档,该文档要求在类标头中调用Q_OBJECT宏才能使用。

Secondly, as your Node inherits QGraphicsItem , I would suggest to use qgraphicsitem_cast instead, which is faster in different manner when processing or filtering items present in a scene. 其次,由于您的Node继承了QGraphicsItem ,因此我建议改用qgraphicsitem_cast ,它在处理或过滤场景中存在的项目时以不同的方式更快。 Adaptation from the doc 文档改编

 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
}

This was actually much simpler than I thought, and my problem actually related to the fact that the node->usedWorkplace() method couldn't return anything, as the Workplace* wasn't initialized before I tried to go get it. 这实际上比我想象的要简单得多,而我的问题实际上与以下事实有关: node->usedWorkplace()方法无法返回任何内容,因为在尝试获取Workplace*之前未对其进行初始化。 Dumb, I know... 笨蛋,我知道...

As such, I simply initialized the pointer as 0 (Thank you, @ratchetfreak), and work from there. 这样,我只是将指针初始化为0 (谢谢@ratchetfreak),然后从那里开始工作。 Everything's working fine now. 现在一切正常。

So, when I create the instance of Node , I initialize the pointer as 0 this way: 因此,当我创建 Node的实例时,我将指针初始化为0

nodeToPlace->setWorkplace(0);

Then, when I want to check for the existence of Workplace* for a Node instance: 然后,当我要检查Node实例是否存在Workplace*

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

So I didn't actually need the qobject_cast at all. 因此,我实际上根本不需要qobject_cast

NOTE: this ended up not relating/answering to my question about the qobject_cast failing silently. 注意:这最终与我有关qobject_cast问题无声无息地联系qobject_cast /没有回答。 What I ended up discovering is that the cast will return 0 either if it fails or if you try to cast 0 into something. 我最终发现是, cast将返回0或者如果它失败, 或者如果您尝试投0到的东西。 I think that with my initial code the latter was occurring. 我认为我的初始代码正在发生。

From the IBM Linux Compilers documentation (reports to C++'s dynamic_cast which according to Qt's docs is roughly equivalent): 来自IBM Linux编译器文档 (根据Qt的文档,C ++的dynamic_cast报告大致相同):

The expression dynamic_cast(v) converts the expression v to type T. Type T must be a pointer or reference to a complete class type or a pointer to void. 表达式dynamic_cast(v)将表达式v转换为类型T。类型T必须是指向完整类类型的指针或引用,或指向void的指针。 If T is a pointer and the dynamic_cast operator fails, the operator returns a null pointer of type T. If T is a reference and the dynamic_cast operator fails, the operator throws the exception std::bad_cast. 如果T是指针,并且dynamic_cast运算符失败,则该运算符返回类型T的空指针。 如果T是引用,并且dynamic_cast运算符失败,则该运算符将引发异常std :: bad_cast。

Therefore, I would conclude that I was refering garbage as the arg of the cast, which made my application seg fault (as @hyde mentioned in the comments, hence my +1 to him as well). 因此,我得出的结论是,我将垃圾称为强制转换的arg,这使我的应用程序出现段错误(如注释中提到的@hyde,因此也对他+1)。

If someone has a different opinion and/or explanation, please let me know - I would like to learn more about my errors/mistakes. 如果有人有不同的意见和/或解释,请告诉我-我想详细了解我的错误/错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM