Apakah membuat konstruktor yang memiliki banyak argumen explicit
memiliki efek (berguna)?
Contoh:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Jawaban:
Hingga C ++ 11, ya, tidak ada alasan untuk digunakan explicit
pada konstruktor multi-argumen.
Itu berubah di C ++ 11, karena daftar penginisialisasi. Pada dasarnya, copy-inisialisasi (tetapi bukan inisialisasi langsung) dengan daftar penginisialisasi mengharuskan konstruktor tidak ditandai explicit
.
Contoh:
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
. Saya pribadi tidak akan repot-repot membuat konstruktor multi-argumen explicit
.
Anda akan menemukannya untuk inisialisasi brace (misalnya dalam array)
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;
}
Jawaban luar biasa dari @StoryTeller dan @Sneftel adalah alasan utamanya. Namun, IMHO, ini masuk akal (setidaknya saya melakukannya), sebagai bagian dari pembuktian masa depan perubahan kode. Pertimbangkan contoh Anda:
class A {
public:
explicit A( int b, int c );
};
Kode ini tidak mendapatkan keuntungan secara langsung explicit
.
Beberapa waktu kemudian, Anda memutuskan untuk menambahkan nilai default c
, sehingga menjadi seperti ini:
class A {
public:
A( int b, int c=0 );
};
Saat melakukan ini, Anda memusatkan perhatian pada c
parameter - dalam retrospeksi, itu harus memiliki nilai default. Anda tidak perlu fokus pada apakah A
itu sendiri harus dibangun secara implisit. Sayangnya, perubahan ini membuat explicit
relevan kembali.
Jadi, untuk menyampaikan bahwa seorang ctor explicit
, mungkin ada gunanya melakukannya saat pertama kali menulis metode.
explicit
yang sudah ada di sana selamanya, dan dukungan teknis akan dibanjiri dengan panggilan tentang perubahan itu dan menghabiskan berjam - jam menjelaskan bahwa explicit
itu hanya kebisingan, dan menghapusnya tidak berbahaya. Secara pribadi, saya tidak pandai memprediksi masa depan; cukup sulit untuk memutuskan seperti apa tampilan antarmuka sekarang .
Inilah lima sen saya untuk diskusi ini:
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;
}
Seperti yang dapat Anda lihat dengan mudah, explicit
mencegah dari menggunakan daftar penginisialisasi bersama dengan bar
fungsi bacause konstruktor struct Bar
dideklarasikan sebagai explicit
.