В большинстве случаев неявное преобразование является проблемой, когда оно позволяет скомпилировать код (и, возможно, сделать что-то странное) в ситуации, когда вы сделали что-то, чего не хотели, и скорее код не скомпилируется, но вместо этого некоторое преобразование позволяет код для компиляции и выполнения чего-то странного.
Например, у iostreams есть преобразование в void *
. Если вы немного устали и наберете что-то вроде: std::cout << std::cout;
, это на самом деле скомпилирует - и даст какой-то бесполезный результат - обычно что-то вроде шестнадцатеричного числа из 8 или 16 цифр (8 цифр в 32-битной системе, 16 цифр в 64-битной системе).
В то же время я чувствую себя обязанным указать на то, что многие люди, похоже, получили почти рефлексивное неприятие любых неявных обращений. Есть классы, для которых неявные преобразования имеют смысл. Например, прокси-класс допускает преобразование в один другой конкретный тип. Преобразование в этот тип никогда не является неожиданным для прокси, потому что это просто прокси - то есть это то, что вы можете (и должны) считать полностью эквивалентным типу, для которого это прокси - за исключением Конечно, чтобы сделать что-то хорошее, он должен реализовать некоторое специальное поведение для какой-то конкретной ситуации.
Например, несколько лет назад я написал класс bounded<T>
, который представляет (целочисленный) тип, который всегда остается в указанном диапазоне. Кроме того, он отказывается присваивать значение за пределами указанного диапазона, он действует точно так же, как и базовый тип intger. Это делает это (в значительной степени), обеспечивая неявное преобразование в int. Почти все, что вы делаете с ним, он будет действовать как int. По сути, единственное исключение - когда вы присваиваете ему значение - тогда оно будет выдавать исключение, если значение выходит за пределы диапазона.