为什么我可以将 QObject* 分配给 QObject?

Why can I assign a QObject* to a QObject?

考虑以下代码:

#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 类型的对象。 (此外,newed 对象永远不会 deleted,导致内存泄漏。)

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

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