Почему это компилируется и есть ли переключатель компилятора, который может заставить компилятор сообщать об этом как об ошибке или предупреждении? - PullRequest
5 голосов
/ 11 октября 2011

Я нашел этот пример, когда запустил 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 ++, и он не выводил никаких предупреждений.

EDIT

Спасибо за подсказки. ложь, кажется, имеет особое отношение. Если я сделаю

return true;

Я получаю:

error: conversion from ‘bool’ to non-scalar type ‘QString’ requested

Я использую g ++ 4.4.3 в Ubuntu. Как указано в других комментариях, другие компиляторы сообщают о проблеме.

1 Ответ

7 голосов
/ 11 октября 2011

false равно нулю. Ноль - это особый случай, который представляет нулевой указатель и будет приведен к любому типу указателя без предупреждения.

Я весьма удивлен, что компилятор допустил это как одношаговое преобразование, и не рассматривал это как двухшаговое преобразование из boolean в int, затем int в char* - два пошаговые преобразования не выполняются неявно.

...