Considérons le code suivant:
#include class A : public QObject { Q_OBJECT public: A(QObject* parent = 0) : QObject(parent) {} } int main() { A a = new A(); return 0; }
Pourquoi puis-je assigner un object de type A*
à une variable de type A
sans que le compilateur (ou le runtime) ne se plaint?
Dans ce code, le constructeur de A
est utilisé pour convertir un A*
en un object de type A
, au lieu de l’ affecter . En général, le compilateur est autorisé à utiliser implicitement un constructeur correspondant en tant qu’opérateur de conversion. Le code suivant est donc le code légal:
struct B { B(int i){} } int main() { B b = 5; return 0; }
Dans le code de la question, le nom A*
non nommé résultant de l’opérateur new
est utilisé comme argument parent
du constructeur de A
Ceci est permis car A
est dérivé de QObject
(et correspond donc à la liste des arguments). Cependant, il s’agit clairement d’un comportement indésirable, car a
n’est pas l’object renvoyé par new
, mais un object de type A
lié à cet object. (En outre, le new
object ‘ed n’est jamais delete
d, ce qui entraîne une fuite de mémoire.)
Pour éviter ce genre d’erreur subtile, il est généralement conseillé de rendre explicit
le constructeur des classes QObject
QObject afin d’empêcher le compilateur de l’utiliser de manière erronée en tant qu’opérateur de conversion. (Ceci s’applique également à des situations similaires, pas seulement à Qt.) Avec le code modifié suivant, le compilateur intercepte l’erreur:
class A : public QObject { Q_OBJECT public: explicit A(QObject* parent = 0) : QObject(parent) {} }