Ответ
Ключевое слово explicit применяется к конструкторам с одним параметром (или с несколькими, где все параметры, кроме первого, имеют значения по умолчанию) для запрета неявных преобразований типов. Это предотвращает неожиданное и потенциально ошибочное создание объектов компилятором.
Проблема без explicit:
class StringWrapper {
public:
StringWrapper(const char* str) { /* ... */ } // Неявное преобразование разрешено
};
void processString(const StringWrapper& sw) { /* ... */ }
int main() {
processString("hello"); // Компилятор неявно создаст временный объект StringWrapper.
// Это может быть неочевидно и привести к трудноуловимым ошибкам.
}
Решение с explicit:
class StringWrapper {
public:
explicit StringWrapper(const char* str) { /* ... */ } // Явный конструктор
};
void processString(const StringWrapper& sw) { /* ... */ }
int main() {
// processString("hello"); // Ошибка компиляции: нельзя преобразовать 'const char*' в 'StringWrapper'
processString(StringWrapper("hello")); // OK: явное создание объекта
StringWrapper sw = "world"; // Ошибка: copy-initialization не сработает
StringWrapper sw2("world"); // OK: direct-initialization
}
Когда использовать: Для классов, где неявное преобразование из типа параметра в тип класса не имеет смысла или опасно (например, классы-обертки, "умные" указатели, контейнеры). Конструкторы std::vector с одним параметром size_t являются explicit, чтобы избежать случайного создания вектора из целого числа.