2009-03-13 28 views
8

Bạn có thể cho tôi biết tại sao đoạn code sau đây được đưa ra cho tôi những lỗi sau - tiếng gọi của quá tải "C (int)" là mơ hồC++ - Constructor quá tải - tư nhân và công cộng

tôi sẽ nghĩ rằng kể từ C (char x) là riêng tư, chỉ có C (float) ctor có thể nhìn thấy từ bên ngoài và cần được gọi bằng cách chuyển đổi int sang float.

Nhưng đó không phải là trường hợp.

class C 
{ 
    C(char x) 
    { 
    } 
public: 
    C(float t) 
    { 
    } 
}; 

int main() 
{ 
    C p(0); 
} 

Trả lời

18

Điều này được thảo luận trong "Hiệu quả C++" của Scott Meyer. Lý do này là mơ hồ là họ muốn đảm bảo rằng chỉ đơn thuần là thay đổi khả năng hiển thị của một thành viên sẽ không thay đổi ý nghĩa của mã đã tồn tại ở nơi khác.

Nếu không, giả sử lớp C của bạn nằm trong tiêu đề ở đâu đó. Nếu bạn có một thành viên riêng (int), mã bạn trình bày sẽ gọi C (float). Nếu vì một lý do nào đó, thành viên C (int) đã được công khai, mã cũ sẽ đột nhiên gọi thành viên đó, mặc dù cả mã cũ cũng như chức năng được gọi là đã thay đổi.

EDIT: Các lý do khác:

Thậm chí tệ hơn, giả sử bạn có 2 chức năng sau:

C A::foo() 
{ 
    return C(1.0); 
} 

C B::bar() 
{ 
    return C(1.0); 
} 

Hai chức năng có thể gọi chức năng khác nhau tùy thuộc vào việc một trong hai foo hoặc thanh được tuyên bố như một người bạn của C, hoặc A hoặc B thừa kế từ nó. Có giống hệt nhau mã gọi các chức năng khác nhau là đáng sợ.

(Đó có lẽ không phải cũng đặt như thảo luận Scott Meyer, nhưng đó là ý tưởng.)

+1

Hmm, đây dường như là một lời giải thích tuyệt vời lúc đầu. Nhưng ... nó vẫn có thể tạo lớp _without_ một int-ctor, sau đó sau đó _add_ rằng ctor quá cũ mã đột nhiên bắt đầu gọi thành viên mới ... Vì vậy, bảo vệ này chỉ tạo ra một cảm giác an toàn giả. –

+0

Điểm tốt. Tôi sẽ thêm nhiều hơn nữa. –

7

0 là một loại int. Bởi vì nó có thể được đúc hoàn toàn hoặc là một phao hoặc bằng nhau, cuộc gọi là mơ hồ. Khả năng hiển thị không liên quan cho các mục đích này.

Hoặc đặt 0.0, 0., hoặc 0.0f, hoặc thoát khỏi các nhà xây dựng C(char) hoàn toàn.

Edit: phần có liên quan của tiêu chuẩn, phần 13,3:

3) [...] Nhưng, một khi các chức năng ứng cử viên và danh sách đối số đã được xác định, việc lựa chọn các chức năng tốt nhất là như nhau trong mọi trường hợp:

  • Đầu tiên, một tập hợp con của các hàm ứng cử viên — được chọn để tạo thành một tập hợp các hàm khả thi (13.3.2).
  • Sau đó, chức năng khả thi tốt nhất được chọn dựa trên chuỗi chuyển đổi ngầm định (13.3.3.1) cần để đối sánh từng đối số với tham số tương ứng của mỗi hàm khả thi.

4) Nếu chức năng khả thi tốt nhất tồn tại và là duy nhất, độ phân giải quá tải thành công và tạo kết quả. Nếu không, quá trình phân giải quá tải sẽ không thành công và lời gọi bị hỏng. Khi độ phân giải quá tải thành công, và không thể truy cập chức năng khả thi tốt nhất (điều 11) trong ngữ cảnh mà nó được sử dụng, chương trình bị hỏng.

Lưu ý rằng khả năng hiển thị không thuộc quá trình lựa chọn.

+0

Bạn không giải thích tại sao tính riêng tư không nghiêng độ phân giải quá tải. –

+0

+1 đây là một nửa câu chuyện, nhưng không giải quyết khả năng hiển thị –

+0

Thay đổi xuống để upvote cho trích dẫn tiêu chuẩn. –

-1

Tôi không nghĩ rằng:

C p(0); 

đang được chuyển đổi sang:

C(float t) 

bạn có thể cần phải làm:

C p(0.0f); 
+0

Không, đó không phải là vấn đề. Chuyển đổi ngầm từ '0' sang float * hiện * tồn tại. –

Các vấn đề liên quan