Ответ 1
Это немного сложно...
Помните, что qobject_cast<T>(obj)
- это способ динамического перевода QObject
в целевой тип T
, который также выводится из QObject
. Теперь, чтобы это сработало, макрос Q_OBJECT
должен быть включен в определение класса T
.
По-видимому, вызов qt_check_for_QOBJECT_macro
предназначен для проверки того, что класс действительно содержит макрос Q_OBJECT. Когда макрос расширяется, он содержит следующие определения:
template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const
{ int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }
template <typename T1, typename T2>
inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }
Итак, если у вас есть объект x
типа T
и объект y
типа U
, вызов x->qt_check_for_QOBJECT_macro(y)
вызывает функцию qYouForgotTheQ_OBJECT_Macro
с параметрами типов T*
и U*
. Поскольку функция шаблонизирована с помощью параметра одного типа, типы T
и U
должны быть одинаковыми.
Теперь, если вы вызываете x->qt_check_for_QOBJECT_macro(x)
, тогда вы должны ожидать, что типы будут одинаковыми, а для компиляции тривиально удастся. Однако помните, что this
имеет тот же тип, что и класс, в котором был определен метод. Поэтому, если x
относится к классу, который был получен из T, но не содержит собственного определения qt_check_for_QOBJECT_macro
, вызов будет потерпеть неудачу.
Итак, у нас есть способ проверить, имеет ли целевой тип T правильный механизм динамического переноса, но у нас нет объекта типа T, который еще не вызвал этот метод. Это для reinterpret_cast<T>(0)
. Нам не нужен фактический объект как this
, так как компилятору нужны только типы объектов для проверки. Вместо этого мы вызываем метод с нулевым указателем типа T.
Я не думаю, что это разрешено стандартом С++, но работает, так как this
фактически не используется внутри метода.