การสร้างคอนสตรัคเตอร์ที่มีหลายอาร์กิวเมนต์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?
};
คำตอบ:
จนถึง C ++ 11 ใช่ไม่มีเหตุผลที่จะใช้explicit
กับตัวสร้างหลายอาร์กิวเมนต์
ที่เปลี่ยนแปลงใน C ++ 11 เนื่องจากรายการ initializer โดยพื้นฐานแล้วการเริ่มต้นการคัดลอก (แต่ไม่ใช่การเริ่มต้นโดยตรง) ด้วยรายการตัวเริ่มต้นจำเป็นต้องไม่ทำเครื่องหมาย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
แต่เป็นเพียงเพราะมันเป็นส่วนขยายของตรรกะของความหมายที่มีอยู่สำหรับ ฉันจะไม่รบกวนการสร้าง multi-arg constructor เป็นการ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
.