7

It recently came to my attention chức năng thành viên hoàn toàn bóng các chức năng miễn phí có cùng tên khi ở trong lớp học. Và hoàn toàn tôi có nghĩa là mọi chức năng tự do có cùng tên không được xem xét cho độ phân giải quá tải. Tôi có thể hiểu lý do tại sao nó được thực hiện với somwthing như thế này:Tại sao các hàm thành viên của lớp đổ bóng các hàm miễn phí có cùng tên?

void f(); 

struct S 
{ 
    void f(); 

    void g() 
    { 
     f(); // calls S::f instead of ::f 
    } 
}; 

nơi các hàm có chữ ký giống hệt nhau, nó chỉ tự nhiên như phạm vi biến hoạt động theo cùng một cách. Nhưng tại sao cấm các cuộc gọi unambigious nơi chức năng miễn phí có chữ ký khác nhau như thế này:

void f(); 

struct S 
{ 
    void f(int x); 

    void g() 
    { 
     f(); // fails to compile attempting to call S::f, which has wrong signature 
    } 
}; 

Tôi không yêu cầu làm thế nào để gọi một shadowed chức năng miễn phí từ bên trong lớp. Những gì tôi muốn biết là lý do đằng sau thiết kế này.

+1

Bạn có thể cần phải hỏi Bjarne Stroustrup! – peacemaker

+1

Tìm kiếm như thế có nghĩa là danh sách các hàm ứng cử viên được tạo ra luôn nhỏ. Đó là tốt cho thời gian biên dịch, bạn có thể tưởng tượng nếu nó tìm kiếm tất cả các ứng cử viên có thể (bao gồm cả ADL) và có rất nhiều mẫu nó sẽ rất nhanh chóng nhận được rất chậm. Nó cũng phản ánh cách sử dụng và ngữ nghĩa mong muốn trong hầu hết các trường hợp. Bình thường khi bạn nói 'foo' cái 'foo' bạn đang nghĩ đến là cái gần nhất. Nếu nó không phải là gần nhất nó có thể chỉ cần thực hiện một sai lầm. Một lỗi là tốt hơn so với những thứ kỳ lạ xảy ra tại thời gian chạy. Giữ mọi thứ cục bộ là hành vi tốt. – Flexo

+2

bạn có thể thưởng thức bản trình bày này trên Tra cứu tên: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of -n – MFH

Trả lời

6

Để tra cứu tên không đủ điều kiện, chỉ một phạm vi được xem xét và nếu tìm kiếm trong phạm vi đó không mang lại bất kỳ kết quả nào, phạm vi cao hơn tiếp theo sẽ được tìm kiếm. Trong trường hợp của bạn, chỉ tìm kiếm phạm vi của S.

Nhưng tại sao cấm các cuộc gọi unambigious nơi chức năng miễn phí có chữ ký khác nhau như thế này:

Vấn đề là tra cứu tên không liên quan đến bản thân với bất cứ điều gì ngoại trừ cái tên, các định danh. Nó hoàn toàn không biết gì về thực tế là bạn muốn gọi một hàm, nó chỉ thấy một định danh. Tra cứu tên tương tự xảy ra nếu bạn chỉ sử dụng auto x = f; và nếu bạn nghĩ theo cách đó, có nhiều lý do rất tốt khiến bạn chỉ muốn phạm vi tìm kiếm rất hạn chế. Bất cứ điều gì khác sẽ làm người dùng ngạc nhiên.

+1

"_ Vấn đề là tra cứu tên không liên quan đến chính nó với bất cứ thứ gì ngoài tên, số nhận dạng._" Trong hầu hết các ngôn ngữ, điều đó là đúng. Không có trong C++. – curiousguy

2

Tôi không thể cung cấp câu trả lời có thẩm quyền (Có thể một số người đã nhớ báo giá từ Design and Evolution of C++ hoặc thực sự đã ở trong ủy ban tại thời điểm đó), nhưng dự đoán đầu tiên của tôi sẽ thất bại trong trường hợp bạn hiển thị. Nó rất dễ dàng để quên có bao nhiêu điều trong phạm vi tại một thời điểm nhất định. Ngoài ra độ phân giải quá tải có thể khá phức tạp và có thể có đối số mặc định và chuyển đổi. Vì vậy, tôi muốn có phạm vi giới hạn nhất trong trường hợp đó để luôn luôn chắc chắn chính xác những gì đang được gọi.

+0

Đầu cơ, nhưng đó cũng là linh cảm của tôi. Thật khó để phân biệt giữa việc dựa vào các tìm kiếm và lỗi chính tả điên rồ. – Flexo

+0

"_ Thật dễ dàng để quên có bao nhiêu điều trong phạm vi tại một thời điểm nhất định._" đây là một đối số cực kỳ mạnh mẽ cho việc không giấu tên ở đây. – curiousguy

3

Có một đặc biệt, rất đáng ngạc nhiên, quy tắc (nhưng nó không áp dụng đối với ví dụ của bạn) nói rằng một khi một tên thành viên lớp được tìm thấy bằng cách tra cứu tên, không có phạm vi không gian tên được tìm kiếm:

#include <string> 

struct C { 
    std::string s; 

    explicit C (std::string); 

    void swap (C& rhs) { 
     swap (s, rhs.s); // error: swap is C::swap 
    } 
}; 

void swap (C& lhs, C& rhs) { 
    swap (lhs.s, rhs.s); // std::swap(string,string) 
} 

IMO, đây là sự điên rồ.

Nhưng tại sao cấm các cuộc gọi unambigious nơi chức năng miễn phí có chữ ký khác nhau như thế này:

Tên tra cứu xảy ra trước khi độ phân giải quá tải:

  • Nếu tra cứu là mơ hồ, quá tải độ phân giải không được thực hiện.
  • Nếu không có chức năng khả thi nào được tìm thấy bằng tra cứu tên, không tìm thấy lần tra cứu nào khác.

Quy tắc đủ phức tạp mà không có "phản hồi" giữa quá tải và tra cứu tên. Tôi sẽ đề nghị đơn giản hóa (như loại bỏ thành viên ẩn quy tắc tên phạm vi không gian tên và loại bỏ tra cứu tên mơ hồ) thay vì phức tạp.

+0

Đây không phải là điên như bạn nghĩ. Tra cứu tên dừng lại khi tìm thấy một kết quả phù hợp (được nêu ở đâu đó xung quanh §3.4 hoặc hơn), và một thứ tự chính xác được đưa ra từ bên trong ra ngoài. Vì vậy, nếu một thành viên với một tên được tìm thấy, nó dừng lại. Không bất ngờ. – Damon

+0

@Damon "_Tìm kiếm tên sẽ dừng khi kết hợp được tìm thấy_" không, như lần hiển thị cuộc gọi 'hoán đổi' thứ hai của tôi – curiousguy

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