Имеет ли какой-либо (полезный) эффект конструктор, имеющий несколько аргументов explicit
?
Пример:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Имеет ли какой-либо (полезный) эффект конструктор, имеющий несколько аргументов explicit
?
Пример:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
До тех пор, пока С++ 11, да, нет причин использовать explicit
в конструкторе multi-arg.
Это изменяется в С++ 11 из-за списков инициализаторов. В принципе, инициализация копирования (но не прямая инициализация) с помощью списка инициализаторов требует, чтобы конструктор не был помечен explicit
.
Пример:
struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };
Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok
Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY
Вы наткнулись на него для инициализации скобки (например, в массивах)
struct A {
explicit A( int b, int c ) {}
};
struct B {
B( int b, int c ) {}
};
int main() {
B b[] = {{1,2}, {3,5}}; // OK
A a1[] = {A{1,2}, A{3,4}}; // OK
A a2[] = {{1,2}, {3,4}}; // Error
return 0;
}
Отличные ответы от @StoryTeller и @Sneftel - главная причина. Тем не менее, IMHO, это имеет смысл (по крайней мере, я это делаю), поскольку часть будущей проверки позже изменяет код. Рассмотрим ваш пример:
class A {
public:
explicit A( int b, int c );
};
Этот код напрямую не использует explicit
.
Через некоторое время вы решите добавить значение по умолчанию для c
, чтобы оно стало следующим:
class A {
public:
A( int b, int c=0 );
};
При этом вы сосредотачиваетесь на параметре c
- в ретроспективе, оно должно иметь значение по умолчанию. Вы не обязательно фокусируетесь на том, должен ли сам A
быть неявным. К сожалению, это изменение снова имеет значение explicit
.
Итак, для того, чтобы сообщить, что ctor explicit
, он может заплатить за это при первом написании метода.
Вот мои пять центов к этому обсуждению:
struct Foo {
Foo(int, double) {}
};
struct Bar {
explicit Bar(int, double) {}
};
void foo(const Foo&) {}
void bar(const Bar&) {}
int main(int argc, char * argv[]) {
foo({ 42, 42.42 }); // valid
bar({ 42, 42.42 }); // invalid
return 0;
}
Как вы можете легко видеть, explicit
предотвращает использование списка инициализаторов наряду с функцией bar
, поскольку конструктор struct Bar
объявляется как explicit
.