Việc tạo một hàm tạo có nhiều đối số explicit
có tác dụng (hữu ích) nào không?
Thí dụ:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Câu trả lời:
Cho đến C ++ 11, vâng, không có lý do gì để sử dụng explicit
trên một hàm tạo nhiều đối số.
Điều đó thay đổi trong C ++ 11, do danh sách trình khởi tạo. Về cơ bản, quá trình sao chép-khởi tạo (nhưng không phải khởi tạo trực tiếp) với danh sách bộ khởi tạo yêu cầu rằng hàm tạo không được đánh dấu explicit
.
Thí dụ:
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
. Cá nhân tôi sẽ không bận tâm đến việc tạo các hàm tạo đa đối số explicit
.
Bạn sẽ tình cờ gặp nó để khởi tạo dấu ngoặc nhọn (ví dụ: trong mảng)
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;
}
Những câu trả lời xuất sắc của @StoryTeller và @Sneftel là lý do chính. Tuy nhiên, IMHO, điều này có ý nghĩa (ít nhất là tôi làm điều đó), như một phần của việc kiểm chứng trong tương lai những thay đổi sau này đối với mã. Hãy xem xét ví dụ của bạn:
class A {
public:
explicit A( int b, int c );
};
Mã này không trực tiếp hưởng lợi từ explicit
.
Một thời gian sau, bạn quyết định thêm giá trị mặc định cho c
, vì vậy giá trị này trở thành:
class A {
public:
A( int b, int c=0 );
};
Khi làm điều này, bạn đang tập trung vào c
tham số - khi nhìn lại, nó phải có giá trị mặc định. Bạn không nhất thiết phải tập trung vào việc liệu A
bản thân nó có nên được xây dựng ngầm hay không. Thật không may, thay đổi này explicit
có liên quan trở lại.
Vì vậy, để truyền đạt rằng một ctor là explicit
, nó có thể phải trả tiền để làm như vậy khi lần đầu tiên viết phương thức.
explicit
thứ đã tồn tại mãi mãi và bộ phận hỗ trợ công nghệ sẽ tràn ngập các cuộc gọi về sự thay đổi đó và dành hàng giờ để giải thích rằng đó explicit
chỉ là tiếng ồn và việc loại bỏ nó là vô hại. Cá nhân tôi không giỏi dự đoán tương lai cho lắm; thật khó để quyết định giao diện sẽ trông như thế nào bây giờ .
Đây là năm xu của tôi cho cuộc thảo luận này:
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;
}
Như bạn có thể dễ dàng thấy, explicit
ngăn không cho sử dụng danh sách bộ khởi tạo cùng với bar
hàm phụ trợ vì hàm tạo của struct Bar
được khai báo là explicit
.