Повторение Q_DISABLE_COPY в производных классах QObject

В Qt есть макрос, который позволяет объявлять частные конструкторы и операторы присваивания для классов: http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#Q_DISABLE_COPY

Говорят, что этот макрос должен использоваться для всех классов QObject (особенно QWidget).

Я понимаю, как это работает и почему это полезно.

Что я не понимаю: Есть ли причина повторять Q_DISABLE_COPY в моих производных классах QObject, а QObject уже содержит Q_DISABLE_COPY, и благодаря этому эффективно предотвращается копирование моих производных классов?

Ответ 1

Сообщение об ошибке, которое может быть напечатано при попытке скопировать производный класс, может относиться к QObject вместо вашего кода, поэтому ошибка может показаться запутанной. Например, используя Visual Studio 2012 для компиляции этого кода

class MyClass : public QObject
{

};

int main(int argc, char *argv[])
{
    Q_INIT_RESOURCE(application);

    MyClass obj1;
    MyClass obj2(obj1);

    QApplication app(argc, argv);
    app.setOrganizationName("QtProject");
    app.setApplicationName("Application Example");
    MainWindow mainWin;
    mainWin.show();
    return app.exec();
}

приводит к этой ошибке (и куча ссылок на QObject).

ошибка: C2248: 'QObject:: QObject': не может получить доступ к частному члену объявлен в классе QObject

Изменение MyClass на

class MyClass : public QObject
{
private:
    Q_DISABLE_COPY(MyClass)
public:
    MyClass();
};

приводит к гораздо более удобной для пользователя группе ошибок, относящихся к MyClass, начиная с

Ошибка: C2248: "MyClass:: MyClass": не удается получить доступ к частному члену объявлен в классе "MyClass"

Я думаю, что второе сообщение об ошибке легче понять для кого-то, нового для Qt.

Определение MyClass также самодокументируется, если Q_DISABLE_COPY включен в определение класса для любого, кто читает код.

Другой причиной повторения определения в производных классах является защита вашего кода от будущих ошибок, если реализация QObject изменена, чтобы больше не использовать Q_DISABLE_COPY(). Хотя это маловероятно, документируя это требование, разработчики Qt оставили себе небольшое пространство для маневра, если они когда-либо решат изменить QObject.