2008-10-21 29 views
80

Tôi đang sử dụng khai báo 'using' trong C++ để thêm std :: string và std :: vector vào vùng tên cục bộ (để lưu gõ không cần thiết 'std ::' s).Phạm vi của việc sử dụng "khai báo" trong C++ là gì?

using std::string; 
using std::vector; 

class Foo { /*...*/ }; 

Phạm vi trong tuyên bố này là gì? Nếu tôi làm điều này trong một tiêu đề, nó sẽ tiêm các khai báo 'sử dụng' này vào mọi tệp cpp bao gồm tiêu đề?

+17

Chỉ trong trường hợp không rõ câu trả lời ở đây: - ** Không đặt khai báo 'using' (hoặc' using') ở phạm vi tệp trong tệp/tiêu đề bao gồm! ** gây đau đầu cho người dùng tiêu đề. –

+0

Trên thực tế, không đặt khai báo 'using' (chỉ thị fortiori * *) trong tiêu đề ** ở tất cả **, * ngay cả trong không gian tên! * Xem [phạm vi sử dụng khai báo trong một không gian tên] (http://stackoverflow.com/q/6175705/2025416) cho các vấn đề này gây ra. –

Trả lời

53

Khi bạn # bao gồm tệp tiêu đề trong C++, nó đặt toàn bộ nội dung của tệp tiêu đề vào vị trí bạn đã đưa vào tệp nguồn. Vì vậy, bao gồm tệp có tuyên bố using có cùng tác dụng chính xác khi đặt tờ khai using ở đầu mỗi tệp bao gồm tệp tiêu đề đó.

+43

... thường là một điều xấu. – Catskul

+13

Nhưng nếu bạn đặt khai báo 'using' bên trong một' không gian tên', nó được giới hạn trong phạm vi của không gian tên đó, vì vậy nói chung là OK (với các thông báo trước về các nhu cầu và kiểu dáng cụ thể của bạn). – Zero

+1

... nhưng nếu bạn đặt bên trong một không gian tên, hãy đảm bảo bạn không làm điều đó để cố gắng tìm một thứ gì đó bình thường là một ý tưởng tồi, giống như bạn không thể mã hóa các phương thức lớp được khai báo bên ngoài vùng tên Y bên trong không gian tên X khác, chỉ để bạn có thể sử dụng cục bộ vùng tên X. Thats lý do tại sao chúng ta đã sử dụng namespace :: resolvers ngay từ đầu. Nếu nó lớn của một vấn đề đánh máy, hoặc là một vĩ mô (mà có thể dễ dàng dẫn đến mùi mã) hoặc tốt hơn, cô lập nó vào nguồn riêng của nó .cpp nơi bạn sẽ sử dụng không gian tên đó chỉ. – osirisgothra

5

Trong trường hợp được trích dẫn, tệp ("đơn vị dịch"), có nghĩa là có, mọi tệp có chứa nó.

Bạn cũng có thể đặt câu lệnh sử dụng bên trong lớp, trong trường hợp đó, nó chỉ có hiệu lực đối với lớp đó.

Nói chung, nếu bạn cần chỉ định một không gian tên trong một tiêu đề, thường tốt nhất là chỉ cần đủ điều kiện cho mỗi số nhận dạng cần thiết.

+0

Lưu ý rằng khai báo 'using' trong một lớp không hoạt động giống như bên ngoài một lớp - ví dụ bạn không thể sử dụng nó mang' cout' thay vì 'std :: cout' vào phạm vi của lớp. – Zero

2

Điều đó là chính xác. Phạm vi là mô-đun sử dụng khai báo using. Nếu bất kỳ tệp tiêu đề nào mà mô-đun bao gồm có khai báo using, phạm vi của các khai báo đó sẽ là mô-đun đó, cũng như bất kỳ mô-đun nào khác có cùng tiêu đề.

86

Không có gì đặc biệt về tệp tiêu đề sẽ giữ tờ khai using. Đó là một thay thế văn bản đơn giản trước khi biên dịch thậm chí bắt đầu.

Bạn có thể giới hạn một tuyên bố using đến một phạm vi:

void myFunction() 
{ 
    using namespace std; // only applies to the function's scope 
    vector<int> myVector; 
} 
+8

Tôi chưa bao giờ nghĩ mình có thể sử dụng nó bên trong một chức năng! – Agostino

+1

Tôi đã có một loạt các không gian tên đang được sử dụng bởi một tập tin kiểu "conglomerator", và thử nghiệm đơn vị gmock quá tẻ nhạt bởi vì mỗi bài kiểm tra đã sử dụng mọi thứ từ một không gian tên cụ thể, và tôi nghĩ mình phải đủ điều kiện cho mỗi biến . Sử dụng 'using' bên trong một hàm (hoặc thậm chí là một macro' TEST' gtest!) Làm cho cuộc sống của tôi tốt hơn rất nhiều! – dwanderson

4

Phạm vi là bất cứ điều gì phạm vi khai báo sử dụng là trong

Nếu đây là phạm vi toàn cầu, sau đó nó sẽ được ở phạm vi toàn cầu.. Nếu nó nằm trong phạm vi toàn cục của một tệp tiêu đề, thì nó sẽ nằm trong phạm vi toàn cục của mọi tệp nguồn bao gồm tiêu đề.

Vì vậy, lời khuyên chung là tránh sử dụng các khai báo trong phạm vi toàn cầu của tệp tiêu đề.

+2

Điều đó không đủ mạnh. Thay thế tránh với Don't –

+1

Tránh né mạnh hơn không. "Tránh đánh các xe khác" – bobobobo

44

Phạm vi của báo cáo kết quả sử dụng phụ thuộc vào nơi mà nó nằm trong các mã:

  • Được đặt ở phía trên cùng của một tập tin, nó có phạm vi toàn tập tin đó.
  • Nếu đây là tệp tiêu đề, nó sẽ có phạm vi trong tất cả các tệp bao gồm tiêu đề đó. Nói chung, đây là "không phải là một ý tưởng tốt" vì nó có thể có tác dụng phụ bất ngờ
  • Nếu không báo cáo kết quả sử dụng có phạm vi trong khối chứa nó từ quan điểm nó xảy ra với sự kết thúc của khối. Nếu nó được đặt trong một phương thức, nó sẽ có phạm vi trong phương thức đó. Nếu nó được đặt trong một định nghĩa lớp, nó sẽ có phạm vi trong lớp đó.
+4

Tôi nghĩ rằng không thể thêm câu lệnh 'using' vào phạm vi lớp học ...? Tôi đã có cùng một câu hỏi như OP vì điều đó như tôi muốn tránh gõ 'std ::' trên khắp nơi. Tôi có các lớp học sử dụng rất nhiều vectơ với con trỏ thông minh và tiền tố năm ký tự 'std ::' bổ sung thêm nhiều chiều dài dòng - mà tôi thấy là tệ hơn. Vì vậy, tôi đã tự hỏi nếu một 'using' chỉ thị trong không gian tên có chứa các lớp học là ok? (Ngay cả khi trong một tiêu đề.) – thomthom

+0

Còn nếu nó được đặt trong phạm vi của một 'không gian tên {...}' thì sao? – einpoklum

+0

Vì vậy, bạn hoàn toàn có thể viết: {using namespace blabla; class blah {}; } và việc sử dụng đó sẽ chỉ áp dụng cho lớp học? – Dinaiz

1

Có một vài nhận xét thay vì không đủ tiêu chuẩn khi họ nói "Không".Đó là quá nghiêm khắc, nhưng bạn phải hiểu khi nào nó là OK.

Viết using std::string không bao giờ OK. Viết using ImplementationDetail::Foo trong tiêu đề của riêng bạn, khi tiêu đề đó tuyên bố ImplementDetail :: Foo có thể được OK, moreso nếu khai báo sử dụng xảy ra trong không gian tên của bạn. Ví dụ.

namespace MyNS { 
    namespace ImplementationDetail { 
     int Foo; 
    } 
    using ImplementationDetail::Foo; 
} 
+1

Người dùng của tiêu đề sau đó có thể viết 'MyNS :: Foo' –

+0

Một ví dụ tốt hơn là' using boost :: posix_time :: ptime'. Chắc chắn người dùng có thể viết 'MyNS :: ptime' nhưng đó không phải là kết thúc của thế giới, và có thể được bù đắp bởi sự tiện lợi của việc có thể có các chức năng như' MyFunction (ptime a, ptime b) '. – Zero

+4

* Tại sao * là 'sử dụng std :: string' không bao giờ ok? Ngay cả trong không gian tên của riêng bạn để tiết kiệm rất nhiều tiền tố 'std ::'? – thomthom

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