2012-05-24 39 views
12

Xét đoạn mã sau:Có sử dụng không gian tên gây ra ẩn tên không?

namespace C { 
    class X {}; 
} 

namespace A { 
    class X {}; 

    namespace B { 
     using namespace C; 

     X x; 
    } 
} 

Tôi đã chờ đợi loại xC::X do chỉ thị using namespace, nhưng thay vào đó cả VS2010 và trực tuyến LLVM/Clang biên dịch quyết tâm X trong namespace BA::X. Thay đổi chỉ thị sử dụng bằng tuyên bố sử dụng (using C::X), sau đó nó sẽ giải quyết thành C::X như mong đợi.

Tiêu chuẩn nói trên sử dụng chỉ thị [7.3.4.2]:

Một sử dụng-chỉ thị xác định rằng tên trong không gian tên được đề cử có thể được sử dụng trong phạm vi trong đó sử dụng-chỉ xuất hiện sau khi sử dụng -directive. Trong quá trình tra cứu tên không đủ tiêu chuẩn (3.4.1), các tên xuất hiện như thể chúng được khai báo trong không gian tên bao quanh gần nhất chứa cả không gian tên sử dụng và chỉ định được chỉ định.

đọc My của việc này là C::X nên xuất hiện như thể tuyên bố trong namespace B, hiệu quả che giấu A::X. (Các) phần nào của tiêu chuẩn nằm sau sự không nhất quán này giữa việc sử dụng các chỉ thị và sử dụng các khai báo? Có cách nào để giấu tên từ một phạm vi bên ngoài bằng một chỉ thị sử dụng không?

+5

Có thể đầu mối nằm trong * các tên xuất hiện như thể chúng được khai báo trong không gian tên bao quanh gần nhất chứa ** cả ** chỉ thị sử dụng và không gian tên được chỉ định *. Điều đó không phải là '::'? Và nếu vậy, sẽ không tìm thấy 'A :: X' trước (tra cứu đi từ không gian tên bên trong) ... không chắc chắn, nhưng g ++ cũng lấy 'A :: X', vì vậy nó rất * nhất quán trên các trình biên dịch. –

+0

@David Rodríguez - dribeas: Ồ, điều đó sẽ giải thích nó ... –

Trả lời

6

Các chương về sử dụng chỉ thị có vẻ là bằng cách nào đó rõ ràng rằng bạn đang nhìn thấy hành vi dự kiến:

7.3.4p2 Một sử dụng-chỉ thị xác định rằng tên trong không gian tên được đề cử có thể được sử dụng trong phạm vi trong đó chỉ thị sử dụng xuất hiện sau chỉ thị sử dụng. Trong quá trình tra cứu tên không đủ tiêu chuẩn (3.4.1), các tên xuất hiện như thể chúng được khai báo trong không gian tên bao quanh gần nhất có chứa cả hai không gian tên sử dụng và chỉ định được chỉ định.

7.3.4p3 Chỉ thị sử dụng không thêm bất kỳ thành viên nào vào khu vực khai báo mà nó xuất hiện.

Đó là, sử dụng-chỉ thêm các thành viên của không gian tên để tập tra cứu của tổ tiên namespace chung của chỉ thị và không gian tên được sử dụng, không trực tiếp đến phạm vi nơi sử dụng-chỉ Được sử dụng. Điều này được nêu rõ trong trích dẫn thứ hai: nó không thêm bất kỳ thành viên nào vào vùng khai báo của sử dụng-chỉ thị.

Sau đó có một ví dụ mà có nghĩa là để minh họa cho cái gì khác nhưng thực tế cho thấy điều này:

7.3.4p4 [...] Ví dụ khác

namespace A { 
    int i; 
} 
namespace B { 
    int i; 
    int j; 
    namespace C { 
    namespace D { 
     using namespace A; 
     int j; 
     int k; 
     int a = i; // B::i hides A::i 
    } 

Đó ví dụ cuối cùng được sử dụng để làm rõ sự chuyển đổi (và chứa nhiều mã hơn), nhưng nó thực sự tương đương với mã của bạn khi bạn xóa mã phụ.

Vì vậy, có vẻ như trong trường hợp của bạn, sử dụng-chỉ thị không ẩn, mà là ẩn.

+0

Vì vậy, đối với câu hỏi thứ hai của tôi, tôi giả sử nó ** có thể ẩn tên bằng cách sử dụng chỉ thị nhưng chỉ khi chúng nằm trong phạm vi bên ngoài của tổ tiên không gian tên chung. –

+0

Tôi sẽ nói như vậy. Ở mức độ nào đó, tôi sẽ tránh được * sử dụng chỉ thị * hoàn toàn, và chỉ sử dụng * sử dụng-khai báo * hiếm khi. Tra cứu trở nên phức tạp hơn nhiều và khó xác định chính xác những gì được sử dụng, nơi nó được định nghĩa ... Nếu nhu cầu của bạn là làm phẳng việc sử dụng các vùng tên lồng nhau phức tạp, hãy xem xét * bí danh không gian tên *. –

+0

Tôi tránh _using-directives_ trong mã thực của tôi, đây chỉ là một nỗ lực để 'tìm thấy nơi một lớp sống' bằng cách tận dụng các quy tắc tra cứu tên. –

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