Имеет ли explicit
(полезный) эффект создание конструктора с несколькими аргументами ?
Пример:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Ответы:
Вплоть до C ++ 11, да, нет причин использовать конструктор explicit
с несколькими аргументами.
Это изменилось в C ++ 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
explicit
. Я бы лично не стал беспокоиться о создании конструкторов с несколькими аргументами explicit
.
Вы бы наткнулись на него для инициализации скобок (например, в массивах)
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
, это может быть полезно при первом написании метода.
explicit
что было там вечно, и техподдержка будет завалена звонками об этом изменении и часами объяснять, что это 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
.