2011-03-22 30 views
5

Điều này có vẻ một chút về phía sau với tôi nhưng nó hoạt động:Tại sao phạm vi tham số C++ ảnh hưởng đến chức năng tra cứu trong một vùng tên?

#include <iostream> 

namespace nTest 
{ 
    struct cTest {}; 

    void fTest(cTest& x) 
    { 
    std::cout << "nTest::fTest(cTest&) called" << std::endl; 
    } 
} 

int main(void) 
{ 
    nTest::cTest x; 
    fTest(x); //Weird! fTest is resolved since its parameter belongs to nTest. 
    return 0; 
} 

Thông thường, bạn sẽ cần nTest :: để truy cập fTest, nhưng thông số của nó mà thuộc về nTest dường như thêm nTest vào danh sách các thể phạm vi để tìm kiếm fTest. Có vẻ lạ với tôi rằng phạm vi tham số ảnh hưởng đến việc tra cứu hàm.

Điều này biên dịch tốt trong GCC, nhưng tôi tự hỏi là việc sử dụng di động này? Định nghĩa chính thức của cơ chế phạm vi này là gì?

+2

ADL - Tra cứu phụ thuộc đối số (http://en.wikipedia.org/wiki/Argument-dependent_name_lookup) – Nim

+2

Đồng thời đọc câu trả lời được chấp nhận [ở đây] (http://stackoverflow.com/questions/2958648/what-are -the-cạm bẫy-of-adl) –

Trả lời

2

Nó được gọi là Koenig aka Đối số tra cứu phụ thuộc http://en.wikipedia.org/wiki/Argument-dependent_name_lookup

+0

Cảm ơn! Chính xác những gì tôi đang tìm kiếm. – Andrew

+0

@Andrew, vui lòng chấp nhận câu trả lời nếu đó là những gì bạn yêu cầu (nhấp vào dấu kiểm dưới số phiếu bầu) – Nim

1

Nó được thiết kế để tìm các nhà khai thác quá tải, như các nhà điều hành < < bạn sử dụng để gửi một chuỗi để std :: cout. Nếu chúng tôi không có ADL, bạn sẽ phải viết mã của bạn như thế này: std::operator<<(std::cout, "nTest::fTest(cTest&) called").

Không quá đẹp!

Và nếu nó hoạt động cho nhà khai thác, tại sao không làm việc theo cùng một cách cho các chức năng?

12

Đó là ADL (Tra cứu phụ thuộc đối số) hoặc Koenig Lookup (dành cho nhà thiết kế của đối tượng địa lý). Mục đích của tính năng này là trong nhiều trường hợp, cùng một không gian tên sẽ chứa các loại và chức năng có thể được áp dụng cho các loại đó, tất cả đều phù hợp với interface. Nếu ADL không đúng chỗ, bạn sẽ phải mang số nhận dạng vào phạm vi với các khai báo using hoặc bạn sẽ phải hội đủ điều kiện các cuộc gọi.

Điều này trở thành cơn ác mộng vì ngôn ngữ cho phép quá tải của nhà điều hành. Hãy xem xét ví dụ sau:

namespace n { 
    struct test {}; 
    test operator+(test, test const &); // implemented 
}; 
int main() { 
    n::test a,b; 
    n::test c = a + b; //without ADL: c = n::operator+(a, b) 
} 

Trong khi nó có vẻ giống như một tình huống khó xử, hãy xem xét rằng n có thể là không gian tên std, test có thể ostream, và operator+ có thể operator<<:

int main(int argc, char**) { 
    std::cout << "Hi there, there are " << argc << " arguments" << std::endl; 
} 

Without ADL , các cuộc gọi đến operator<< sẽ phải rõ ràng, và hơn nữa bạn sẽ phải biết chúng được thực hiện như một hàm miễn phí so với một phương thức. Bạn có biết rằng std::cout << "Hi" đang gọi một chức năng miễn phí và std::cout << 5 đang gọi một chức năng thành viên? Không nhiều người nhận ra điều đó, và nghiêm túc, hầu như không ai quan tâm. ADL giấu điều đó khỏi bạn.

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