Почему я могу назначить QObject* на 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 без жалоб на компилятор (или время выполнения)?

1 ответ

Решение

В этом коде конструктор A используется для преобразования A* к объекту типа Aвместо того, чтобы назначать это. В общем, компилятору разрешено неявно использовать соответствующий конструктор в качестве оператора преобразования, так что следующее является допустимым кодом:

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

В коде вопроса безымянный A* что вытекает из new оператор используется в качестве parent аргумент конструктора A, Это разрешено с A происходит от QObject (и, следовательно, соответствует списку аргументов). Тем не менее, это явно нежелательное поведение, потому что a не объект, возвращенный new, но объект типа A родом из этого объекта. (В дополнение new'объект никогда не бывает deleted, что приводит к утечке памяти.)

Чтобы избежать такого рода тонких ошибок, обычно рекомендуется сделать конструктор QObjectклассы explicit чтобы компилятор не использовал его как оператор преобразования. (Это относится и к аналогичным ситуациям, а не только к Qt.) В следующем измененном коде компилятор поймает ошибку:

class A : public QObject
{
    Q_OBJECT
    public: 
        explicit A(QObject* parent = 0) : QObject(parent) {}
}
Другие вопросы по тегам