2016-10-04 14 views
8

Chương trình sau đây biên dịch tốt và hoạt động như mong đợi. sản lượng của nó là:Quá tải, hàm VARD và kiểu bool

1
2

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(int a, const char* b, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo1; 
    foo1.Bar("Test", "xx", 1, 2); 
    foo1.Bar(1, "xx", "xx", 2, 2); 
} 

Bây giờ nếu tôi thay đổi int tham số của thứ hai Bar hàm thành boolfoo1.Bar(1, "xx", "xx", 2, 2); vào foo1.Bar(true, "xx", "xx", 2, 2);, sau đó dòng sau sẽ không biên dịch và tôi nhận được lỗi: 'Foo::Bar': 2 overloads have similar conversions:

foo1.Bar("Test", "xx", 1, 2); 

toàn bộ chương trình mà không biên dịch:

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(bool a, const char* b, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo1; 
    foo1.Bar("Test", "xx", 1, 2); // error: 'Foo::Bar': 2 overloads have similar conversions 
    foo1.Bar(true, "xx", "xx", 2, 2); 
} 

Tôi không hiểu tại sao có sự mơ hồ trong trường hợp thứ hai.

EDIT

Nhưng nếu con trỏ ngầm chuyển đổi sang bool, tại sao sau đây biên dịch?

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b) { printf("1\n"); }; 
    void Bar(bool a) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo1; 
    foo1.Bar("Test"); 
    foo1.Bar(true); 
} 
+0

Câu hỏi tương tự http://stackoverflow.com/questions/26413951/overloaded-bool-string-ambiguity – robor78

+0

Điều này không liên quan gì đến hàm variadic, mà bạn đã phát hiện ra rằng bạn đã xây dựng một testcase _minimal_. –

+1

@LightnessRacesinOrbit Tôi vừa chỉnh sửa câu hỏi và thêm một trường hợp kiểm tra tối thiểu mà không có hàm variadic biên dịch ... –

Trả lời

5

Khi bạn đối sánh "Test", "xx", 1, 2 với số const char*, ..., chuỗi chuyển đổi cho đối số đầu tiên có xếp hạng đối sánh chính xác, thứ hai đến thứ tư là chuỗi chuyển đổi dấu ba chấm. Vì vậy, (kết hợp chính xác, dấu ba chấm, dấu chấm lửng, dấu ba chấm).

Khi bạn đối sánh "Test", "xx", 1, 2 với số bool, const char*, ..., chuỗi chuyển đổi đầu tiên cho đối số đầu tiên có xếp hạng chuyển đổi; thứ hai là đối sánh chính xác, thứ ba và thứ tư là chuỗi chuyển đổi dấu ba chấm. Nói cách khác, (chuyển đổi, đối sánh chính xác, dấu ba chấm, dấu ba chấm).

Chuyển đổi nhịp đập chính xác; tất cả mọi thứ đều có dấu chấm lửng (xem [over.ics.rank]). Vì vậy, chúng ta có một tình huống chéo chéo ở đây, trong đó một hàm có chuỗi chuyển đổi tốt hơn cho một đối số và hàm kia có chuỗi chuyển đổi tốt hơn cho một đối số khác. Vì điều kiện cần thiết (nhưng không đủ) cho hàm tốt hơn hàm khác là không có chuỗi chuyển đổi nào kém hơn so với hàm khác ([over.match.best]/1), cả hai hàm này đều không tốt hơn hàm kia.

5

Điều này là tốt:

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(bool a, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo; 
    foo.Bar("Test"); 
} 

Đây không phải là tốt:

#include <stdio.h> 

class Foo 
{ 
public: 
    void Bar(const char* b, ...) { printf("1\n"); }; 
    void Bar(bool a, char another, ...) { printf("2\n"); }; 
}; 

int main() 
{ 
    Foo foo; 
    foo.Bar("Test", 'c'); // Ambiguous! 
} 

Trong trường hợp đầu tiên, phiên bản đầu tiên của Bar() rõ ràng là tốt hơn. Nhưng trong trường hợp thứ hai, nó không còn rõ ràng nữa vì, trong khi phiên bản đầu tiên có kết hợp tốt hơn cho tham số 1, phiên bản thứ hai có kết hợp tốt hơn cho tham số 2.

Câu hỏi còn lại là: tại sao lại sử dụng ' int 'thay vì' bool 'tránh sự mơ hồ? Câu trả lời là một con trỏ có thể chuyển đổi hoàn toàn thành bool nhưng không phải là int.

+0

Tôi đã chỉnh sửa câu hỏi: vậy tại sao trường hợp cuối cùng lại tốt? –

+0

Trường hợp mới thêm của bạn tương đương với trường hợp đầu tiên trong câu trả lời của tôi: nếu bạn gọi bằng 'const char *', phiên bản của Bar() có 'const char *' rõ ràng là tốt hơn; và nếu bạn gọi với 'bool', phiên bản của Bar() có 'bool' rõ ràng là tốt hơn. Chuyển đổi tiềm ẩn vẫn là chuyển đổi. Một hàm không cần phải chuyển đổi đối số của nó, nếu tồn tại, được ưu tiên. –

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