为什么我可以将QObject*赋值给QObject ?

Why can I assign a QObject* to a QObject?

本文关键字:QObject 赋值 为什么 我可以      更新时间:2023-10-16

考虑以下代码:

#include <QObject>
class A : public QObject
{
    Q_OBJECT
    public: 
        A(QObject* parent = 0) : QObject(parent) {}
}
int main()
{
    A a = new A();
    return 0;
}

为什么我可以将类型为A*的对象分配给类型为A的变量而没有编译器(或运行时)抱怨?

在此代码中,A的构造函数用于A*转换为A类型的对象,而不是赋值给。一般情况下,允许编译器隐式地使用匹配构造函数作为转换操作符,因此以下代码是合法的:

struct B
{
    B(int i){}
}
int main()
{
    B b = 5;
    return 0;
}

在问题的代码中,由new运算符得到的未命名的A*用作A的构造函数的parent实参。这是允许的,因为A是从QObject派生的(因此匹配参数列表)。然而,这显然是不希望出现的行为,因为a不是new返回的对象,而是A类型的父对象。(另外,new 'ed对象永远不会是delete ' d,从而导致内存泄漏。)

为了防止这种微妙的错误,通常建议将QObject派生类的构造函数设置为explicit,以防止编译器将其误用为转换操作符。(这也适用于类似的情况,而不仅仅是Qt。)使用以下修改后的代码,编译器将捕获错误:

class A : public QObject
{
    Q_OBJECT
    public: 
        explicit A(QObject* parent = 0) : QObject(parent) {}
}