Зачем используется ключевое слово explicit
Пример первый. Давайте посмотрим на код ниже (да, он собирается и запускается):
class A
{};
class B
{
public:
B(const A &)
{}
};
void foo(const B &)
{}
int main()
{
A a;
foo(a);
}
Я специально убрал все лишние строчки из кода, чтобы вы смогли сосредоточиться на всей абсурдности происходящего: при вызове функции foo тип A преобразовывается в тип В, при этом мой компилятор даже с выкрученными флагами ворнингов не выдал мне никакого предупреждения. Что-то мне подсказывает, что это не то поведение, которое можно завещать потомкам (т.е. разрабам, которые будут работать с вашим кодом).
Если воспользоваться услугами сайта https://cppinsights.io/, можно увидеть, что компилятор преобразует код функции main в следующий:
int main()
{
A a;
foo(B(a));
return 0;
}
Т.е. в момент вызова функции foo из объекта класса A создается временный объект класса B.
Фиксится эта проблема с помощью использования спецификатора explicit перед конструктором класса B.
Продолжение следует.