Да, я думаю, что это плохая практика программирования.
Использование неявных преобразований может привести к очень странным ошибкам.
У меня когда-то была следующая проблема.
Все началось с такой функции:
void doSomething (ClassX x, ClassY y, bool b);
Эта функция была вызвана с кодом, подобным этому:
ClassX x;
ClassY y;
doSomething (x, y, true);
Позже кто-то решил, что аргументы doSomething должны быть изменены, поскольку doSomething теперь также требует экземпляр ClassZ. Кроме того, логический аргумент был истинным во многих случаях, поэтому он был заменен на аргумент по умолчанию, например:
void doSomething (ClassX x, ClassY y, ClassZ z, bool b=true);
Хотя большая часть кода была изменена, показанный ранее вызов не изменился.
Как ни странно, в ClassZ был неявный конструктор, принимающий в качестве аргумента значение bool:
class ClassZ
{
public:
ClassZ(bool b);
};
Произошло следующее. Этот звонок:
ClassX x;
ClassY y;
doSomething (x, y, true);
был тихо преобразован в это компилятором:
ClassX x;
ClassY y;
doSomething (x, y, ClassZ(true), true);
С 4-м аргументом по умолчанию true.
Спустя годы мы выяснили, что что-то не работает должным образом, и после долгих отладок мы обнаружили, что этот вызов стал причиной проблемы.
Таким образом:
- никогда не полагаться на неявные преобразования
- пометить конструкторы с 1 аргументом как явные
- стараться избегать использования аргументов по умолчанию