Apakah membuat konstruktor yang memiliki banyak argumen explicitmemiliki 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 explicitpada 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 cparameter - dalam retrospeksi, itu harus memiliki nilai default. Anda tidak perlu fokus pada apakah Aitu sendiri harus dibangun secara implisit. Sayangnya, perubahan ini membuat explicitrelevan kembali.
Jadi, untuk menyampaikan bahwa seorang ctor explicit, mungkin ada gunanya melakukannya saat pertama kali menulis metode.
explicityang sudah ada di sana selamanya, dan dukungan teknis akan dibanjiri dengan panggilan tentang perubahan itu dan menghabiskan berjam - jam menjelaskan bahwa explicititu 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, explicitmencegah dari menggunakan daftar penginisialisasi bersama dengan barfungsi bacause konstruktor struct Bardideklarasikan sebagai explicit.