为什么我可以将 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
类型的对象。
(此外,new
ed 对象永远不会 delete
d,导致内存泄漏。)
为了防止这种微妙的错误,一般建议将QObject
派生的构造函数设为类 explicit
,以防止编译器误将其用作转换运算符。 (这也适用于类似的情况,不仅适用于 Qt。)
使用以下修改后的代码,编译器将捕获错误:
class A : public QObject
{
Q_OBJECT
public:
explicit A(QObject* parent = 0) : QObject(parent) {}
}
考虑以下代码:
#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) {}
}