2012-04-22 36 views

Trả lời

66

Trong C++, mọi tên đều có phạm vi bên ngoài nó không tồn tại. Phạm vi có thể được xác định theo nhiều cách: nó có thể được xác định bởi không gian tên , chức năng, lớp và chỉ {}.

Vì vậy, không gian tên, toàn cục hoặc cách khác, xác định phạm vi. Không gian tên chung đề cập đến việc sử dụng :: và các biểu tượng được xác định trong không gian tên này được cho là có phạm vi toàn cầu. Một biểu tượng, theo mặc định, tồn tại trong một không gian tên toàn cầu, trừ khi nó được định nghĩa bên trong một khối bắt đầu với từ khóa namespace, hoặc nó là một thành viên của một lớp học, hoặc một biến địa phương của một hàm:

int a; //this a is defined in global namespace 
     //which means, its scope is global. It exists everywhere. 

namespace N 
{ 
    int a; //it is defined in a non-global namespace called `N` 
      //outside N it doesn't exist. 
} 
void f() 
{ 
    int a; //its scope is the function itself. 
      //outside the function, a doesn't exist. 
    { 
     int a; //the curly braces defines this a's scope! 
    } 
} 
class A 
{ 
    int a; //its scope is the class itself. 
      //outside A, it doesn't exist. 
}; 

Cũng lưu ý rằng một tên có thể bị ẩn bởi phạm vi bên trong được xác định bởi không gian tên, chức năng hoặc lớp. Vì vậy, tên a bên trong không gian tên N giấu tên a trong không gian tên chung. Trong cùng một cách, tên trong hàm và lớp ẩn tên trong không gian tên chung. Nếu bạn phải đối mặt với tình huống như vậy, sau đó bạn có thể sử dụng ::a để tham khảo các tên được định nghĩa trong namespace toàn cầu:

int a = 10; 

namespace N 
{ 
    int a = 100; 

    void f() 
    { 
     int a = 1000; 
     std::cout << a << std::endl;  //prints 1000 
     std::cout << N::a << std::endl; //prints 100 
     std::cout << ::a << std::endl; //prints 10 
    } 
} 
+0

Chúng ta nên làm gì nếu chúng ta muốn truy cập 'a' (được định nghĩa trong không gian tên N) bên trong hàm void f() {} – rimiro

+0

@rimiro: Nếu 'a' được khai báo trong phạm vi hàm, bạn không thể truy cập nó từ * bên ngoài * chức năng. – Nawaz

2

Khi bạn khai báo một biến toàn cầu int i ví dụ, chúng ta nói i is in the global namespacehas the global namespace scope. Đó là tất cả.

Trích Từ C++ 03:

3.3.5 Namespace scope 

    The outermost declarative region of a translation unit is also a namespace, called 
    the global namespace. A name declared in the global namespace has global namespace 
    scope (also called global scope). 
4

"Phạm vi" là một thuật ngữ tổng quát hơn "namespace". Mỗi không gian tên, lớp và khối mã xác định phạm vi trong đó các tên được khai báo bên trong nó có thể được sử dụng; một không gian tên là một vùng chứa cho các tên được khai báo bên ngoài các lớp và các hàm.

"Phạm vi toàn cầu" và "không gian tên chung" có thể được sử dụng nhiều hoặc ít thay thế cho nhau; phạm vi của một tên được khai báo trong một không gian tên bao gồm toàn bộ không gian tên đó. Sử dụng "không gian tên" nếu bạn đang đề cập cụ thể đến không gian tên và "phạm vi" nếu bạn đang đề cập đến khả năng hiển thị của các tên bên trong nó.

3

Phạm vi biểu thị tuổi thọ của đối tượng, bạn có thể có biến toàn cục sẽ tồn tại miễn là chương trình của bạn thực thi hoặc bạn có thể có biến với phạm vi chặn sẽ tồn tại miễn là khối mã thực thi. Hãy xem xét ví dụ sau:

#include <iostream> 

int a = 100; 

main() { 
    int a = 200; 

    std::cout << "local a is: " << a << std::endl; 
    std::cout << "global a is: " << ::a << std::endl; 

    return 0; 
} 

Khi thực hiện báo cáo kết quả sẽ in local a is: 200, đó là dự kiến ​​rõ ràng, bởi vì chúng tôi đang xác định lại a trong main mà lá trong phạm vi của nó bao quanh khối. Chúng tôi cũng in toàn cầu ::a mà lại in giá trị mong đợi 100, bởi vì chúng tôi đã yêu cầu không gian tên chung ::.

Ngữ nghĩa không gian tên chủ yếu là hợp lý, đó là cách tách symblos với nhau, với hy vọng tránh xung đột tên, nó không ảnh hưởng đến tuổi thọ của đối tượng.

Phạm vi mặt khác, biểu thị tuổi thọ của một đối tượng, toàn cầu a xuất hiện trước địa phương a vì nó được xây dựng sớm hơn nhiều so với chính được thực hiện. Tuy nhiên, phạm vi cũng là lực lượng một không gian tên trên biểu tượng, nhưng không giống như cách mà namespace thực hiện. Có loại khác nhau của phạm vi, global, class, function, block, file vv ...

Phần khó hiểu là phạm vi đôi khi quá tải để biểu thị sự hiện diện của một biểu tượng đặc biệt, mà là một cái gì đó mượn từ C, nơi khái niệm về không gian tên đã không tồn tại và phạm vi được sử dụng để biểu thị cả tuổi thọ và khả năng hiển thị. Trong C++, tuy nhiên các quy tắc thay đổi một chút, nhưng thuật ngữ phạm vi vẫn được sử dụng theo cùng một cách vì hai ngôn ngữ chia sẻ rất nhiều khái niệm.

+0

Tốt là bạn đã đánh dấu ý tưởng rằng phạm vi là vốn có đối với tuổi thọ của đối tượng. –

2

@Dmitriy Ryajov

Chủ đề này hơi cũ nhưng tôi muốn giúp tôi về điều này. Tôi nghĩ rằng bạn không nên làm cho mọi thứ phức tạp hơn họ thực sự. Scope của số nhận dạng là một phần của chương trình máy tính trong đó số nhận dạng, tên đề cập đến một số thực thể trong chương trình, có thể được sử dụng để tìm pháp nhân được gọi. Vì vậy, phạm vi hạn chỉ áp dụng cho các số nhận dạng và chúng ta không nên kết hợp nó với thời gian tồn tại của đối tượng. Chúng được kết nối một phần nhưng không được trộn lẫn. Tuổi thọ của đối tượng được biểu thị bằng nơi chúng tôi cấp phát bộ nhớ cho đối tượng đó. Vì vậy, ví dụ, nếu một bộ nhớ được cấp phát trên ngăn xếp, nó sẽ được giải phóng ngay sau khi hàm kết thúc. Vì vậy, nó phụ thuộc vào nơi chúng tôi lưu trữ các đối tượng và biểu thị cuộc đời của nó. Phạm vi chỉ nói: "Đây là tên cho một đối tượng và chúng ta có thể sử dụng tên này cho đối tượng cho đến lúc đó và sau đó". Vì vậy, như tôi đã nói, thuật ngữ scope chỉ dành cho số nhận dạng của các đối tượng và thời gian tồn tại là thứ khác được biểu thị bằng nơi chúng tôi lưu trữ đối tượng.

Ngoài ra, tôi muốn nói điều gì đó về linkage liên quan chặt chẽ đến điều này. Điều này đôi khi có thể gây nhầm lẫn. Giả sử chúng tôi có một số số nhận dạng trong số translation unit đề cập đến một số đối tượng. Các số nhận dạng giống nhau trong đơn vị dịch other sẽ chỉ đến cùng một thực thể được biểu thị bằng liên kết hay không. Vì vậy, ví dụ: nếu số nhận dạng có liên kết bên ngoài, chúng tôi có thể tham chiếu đến thực thể mà từ định danh này đề cập đến nhưng từ đơn vị dịch khác bằng cách khai báo từ khóa extern. Bây giờ, giả sử chúng ta không muốn sử dụng thực thể đó trong các đơn vị dịch thuật khác. Sau đó, thực thể sẽ exist cho đến khi chương trình kết thúc nhưng khi chúng tôi không khai báo, chúng tôi sẽ không thể tham khảo. Cũng lưu ý rằng bây giờ tôi trộn lẫn các điều khoản liên kết và đời. Nhưng điều này là do chỉ có global pháp nhân có liên kết bên ngoài. Một định danh bên trong một hàm không thể được tham chiếu đến từ các phần khác của chương trình.

Kết luận: Luôn cố giữ mọi thứ đơn giản. Tôi đã rất ngạc nhiên khi mọi người khác nhau nói về những điều khoản này một cách khác nhau. Toàn bộ quá trình biên dịch riêng biệt là khó hiểu, bởi vì có nhiều thuật ngữ có cùng ý nghĩa và có lẽ mọi người sẽ gặp khó khăn vào thời điểm này.

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