#c #qt #g
#c #qt #g
Вопрос:
Я нашел этот пример, когда запускал PCLint в исходном коде проекта, над которым я работаю. Вот фрагмент кода:
QString foo()
{
return false;
}
Я скомпилировал код и проверил, что он возвращает пустую строку. Реальный пример — большой метод в большом классе, и где-то в какой-то удаленной ветке if было это изолированное
return false;
Хорошо, это плохое кодирование, позор разработчику (используя SVN / blame, я мог бы даже узнать, кто это сделал :-)) но, серьезно, почему компилятор не жалуется?
Моя теория заключается в том, что компилятор переводит
return false;
Для
return QString(((const char *) false));
Однако я не вижу всех элементарных шагов, выполняемых компилятором для вывода этого. Сначала он пробует все конструкторы QString и находит
QString(const * char);
но тогда? Как он определяет, что он может перейти от bool к const char * . Или он автоматически преобразует bool к любому типу указателя каждый раз, когда вы используете bool, где ожидается указатель?
Вторая часть вопроса. Поскольку все эти неявные преобразования типов довольно опасны (зачем разработчику писать ‘return false;’, если они означают «вернуть пустую строку»?), Есть ли способ (например, переключатель компилятора), чтобы о таких ситуациях, по крайней мере, сообщалось как предупреждение? Я попробовал -Wall в g , и он не напечатал никакого предупреждения.
Редактировать
Спасибо за подсказки. false, похоже, имеет особое отношение. Если я сделаю
return true;
Я получаю:
error: conversion from ‘bool’ to non-scalar type ‘QString’ requested
Я использую g 4.4.3 в Ubuntu. Как указывалось в разных комментариях, другие компиляторы сообщают о проблеме.
Комментарии:
1. clang предупреждает об этом, был случай этого некоторое время назад.
2. GCC (по крайней мере, 4.5) предупреждает об этом.
3. Вставьте плагин для
explicit
конструкторов здесь.4. Хорошо, я использую GCC 4.4.3, это может объяснить это. Спасибо.
5. Начиная с GCC 4.5 , новый (включенный по умолчанию) флаг called
-Wconversion-null
выводит предупреждение.
Ответ №1:
false
равно нулю. Ноль — это особый случай, который представляет нулевой указатель и будет приведен к любому типу указателя без предупреждения.
Я очень удивлен, что компилятор разрешил это как одноэтапное преобразование и не рассматривал его как двухэтапное преобразование из boolean
в int
, затем int
в char*
— двухэтапные преобразования не выполняются неявно.
Комментарии:
1. Но false имеет тип bool, а 0 имеет тип int . Выполняется ли приведение автоматически?
2. GCC предупреждает об этом:
warning: converting ‘false’ to pointer type for argument 1 of ‘QString::QString(const char*)’
3. Странно, я не получаю никаких предупреждений. Используя g (Ubuntu 4.4.3-4ubuntu5) 4.4.3. У меня есть -Wall в командной строке.
4. Я тоже был очень удивлен, вот почему я хотел сообщить об этом и попросить объяснений. Кстати, исходный пример был скомпилирован в Visual Studio 8.
5.
bool
является целочисленным типом,false
преобразуется в 0 и является постоянным, и вы можете преобразовать постоянное целочисленное выражение, равное 0 для нулевого указателя. (Это не будет работать сtrue
;true
преобразуется в 1, и для него нет специального значения указателя.)