Những không gian tên là gì và các quy tắc là gì?


9

Lưu ý: câu hỏi này là về name space, không phảinamespace .

Tiêu chuẩn C ++ có một số tài liệu tham khảo name space, nhưng tôi không thấy định nghĩa về điều này. Các tiêu chuẩn nói rằng các nhãn và macro nằm trong các không gian tên khác nhau. Tất cả các tham chiếu khác name spacenằm trong phần tương thích C / C ++, như thế này ( bản nháp hiện tại ):

Đây là một trong số ít sự không tương thích giữa C và C ++ có thể được quy cho định nghĩa không gian tên C ++ mới trong đó một tên có thể được khai báo là một loại và là một loại không trong một phạm vi duy nhất làm cho tên không loại này ẩn tên loại và yêu cầu rằng các từ khóa lớp, struct, union hoặc enum được sử dụng để chỉ tên loại. Định nghĩa không gian tên mới này cung cấp các tiện ích công chứng quan trọng cho các lập trình viên C ++ và giúp sử dụng các kiểu do người dùng định nghĩa giống như có thể với việc sử dụng các kiểu cơ bản.

Định nghĩa không gian tên mới này là gì? Tôi có thể tìm thấy nó trong tiêu chuẩn ở đâu? Các quy tắc chính xác là gì? Các quy tắc dường như phức tạp hơn so với "các loại ẩn không loại". Giống như, điều này không biên dịch:

typedef int Foo; // Foo is a type
void Foo();      // not a type, but compile error, instead of hiding

Nhưng điều này không:

struct Foo { }; // Foo is a type as well
void Foo();     // This hides the type Foo. "struct Foo" refers to the type

Và điều này cũng không được biên dịch:

struct Foo { };   // Type
namespace Foo { } // Non-type, but compiler error instead of hiding

Quan điểm thực tế là một không gian tên là một lớp đơn với tất cả các thành viên công khai (các lớp con). Xin đừng làm phiền tôi :-)
peterh - Tái lập lại

2
@ peterh-RebstateMonica đọc câu hỏi (một lần nữa)
YSC

FWIW, liên kết của bạn liên kết đến các phần có liên quan: Phần phụ bị ảnh hưởng: [class.name] [xem thêm [dcl.typedef]] Bạn có thể xem các phần đó để biết quy tắc hoạt động như thế nào.
NathanOliver

Có ít nhất hai không gian tên: một cho nhãn [stmt.label]/1và một cho macro [cpp]/8.
YSC

1
Điều thú vị (đối với tôi) là cả mô tả và ví dụ cho thấy điều ngược lại với những gì lý do đề cập; một tên loại ẩn một tên không loại. Với trạng thái dự thảo, tôi mong muốn đoạn đó sẽ thay đổi.
molbdnilo

Câu trả lời:


2

Các tên không gian hạn có thể được nhiều hơn cũng như thành lập trong thư mục C Tiêu chuẩn ISO; trích dẫn ISO C11 :

6.2.3 Không gian tên của định danh

Nếu có nhiều hơn một tuyên bố của một mã định danh cụ thể được nhìn thấy tại bất kỳ điểm nào trong một đơn vị dịch thuật, bối cảnh cú pháp sẽ phân biệt sử dụng tham chiếu đến các thực thể khác nhau. Do đó, có các không gian tên riêng biệt cho các loại định danh khác nhau, như sau:

  • tên nhãn (được định nghĩa theo cú pháp khai báo và sử dụng nhãn);
  • các thẻ của cấu trúc, công đoàn và bảng liệt kê (được định nghĩa theo bất kỳ 32) của các từ khóa struct, union hoặc enum);
  • các thành viên của các cấu trúc hoặc đoàn thể; mỗi cấu trúc hoặc liên kết có một không gian tên riêng cho các thành viên của nó (được định nghĩa theo loại biểu thức được sử dụng để truy cập thành viên thông qua toán tử. hoặc ->);
  • tất cả các định danh khác, được gọi là định danh thông thường (được khai báo trong các khai báo thông thường hoặc là các hằng số liệt kê).

Các mới định nghĩa tên không gian của C ++, tuy nhiên, không phải trong bất kỳ cách nào gần đây trong thời gian , và đã được mô tả trong [diff.class] / 1 trong hình thức hiện tại của nó kể từ khi giới thiệu các tiêu chuẩn ISO C ++ Standard trong '98 . Nó chỉ được đề cập ở bất kỳ độ dài nào trong các bối cảnh mà nó khác với ISO C, theo [diff. Class] / 1 được trích dẫn bởi OP.

Afaics chúng ta cần sử dụng ISO C11 / 6.2.3 và kết hợp nó với [diff. Class] / 1 của Tiêu chuẩn ISO C ++ để mô tả đầy đủ và đầy đủ về định nghĩa không gian tên (mới) của C ++ , chúng ta sẽ không quét ISO Tiêu chuẩn C ++, ví dụ: [basic.scope.hiding] , [class.name] / 2 , [stmt.label] / 1 , [cpp.replace] / 8 , v.v. để xem cách thức và nơi áp dụng.

[lớp.name] / 2

Một khai báo lớp giới thiệu tên lớp vào phạm vi nơi nó được khai báo và ẩn bất kỳ lớp, biến, hàm hoặc khai báo nào khác của tên đó trong một phạm vi kèm theo. [...]

[stmt.label] / 1

[...] Nhãn có không gian tên riêng và không can thiệp vào các định danh khác [...]

[cpp.replace] / 1

[...] Có một không gian tên cho tên macro. [...]


1

Trong C (6.2.3 Không gian tên của định danh), khái niệm không gian tên được định nghĩa theo cách sau.

1 Nếu có nhiều hơn một tuyên bố của một mã định danh cụ thể được nhìn thấy tại bất kỳ điểm nào trong một đơn vị dịch thuật, bối cảnh cú pháp phân biệt sử dụng tham chiếu đến các thực thể khác nhau. Do đó, có các không gian tên riêng biệt cho các loại định danh khác nhau, như sau:

- tên nhãn (được định nghĩa theo cú pháp khai báo và sử dụng nhãn);

- các thẻ của cấu trúc, công đoàn và bảng liệt kê (được định nghĩa bằng cách tuân theo any32) của các từ khóa struct, union hoặc enum);

- các thành viên của cấu trúc hoặc đoàn thể; mỗi cấu trúc hoặc liên kết có một không gian tên riêng cho các thành viên của nó (được định nghĩa theo loại biểu thức được sử dụng để truy cập thành viên thông qua toán tử. hoặc ->);

- tất cả các định danh khác, được gọi là định danh thông thường (được khai báo trong các khai báo thông thường hoặc dưới dạng hằng số liệt kê).

Vì vậy, ví dụ tên thẻ cấu trúc có thể trùng với tên hàm vì chúng thuộc các không gian tên khác nhau. Khi bạn chỉ định một cấu trúc với tên thẻ cấu trúc khi bạn phải sử dụng từ khóa struct. Vì vậy, ví dụ những tuyên bố này không xung đột.

struct s
{
    int s;
};

void s( void );

struct s s1;

Trong đoạn mã này, tên thẻ scủa cấu trúc không xung đột với tên hàm s vì tên thẻ sẽ được chỉ định với từ khóastruct .

Trong C ++, bạn được phép sử dụng tên thẻ cấu trúc mà không cần từ khóa struct .

Ví dụ

struct s
{
    int s;
};

s s;

là một mã chính xác. Trong tuyên bố này

s s;

tên của định danh khai báo s ẩn tên cấu trúc. Vì vậy, nếu sau đó bạn sẽ viết ví dụ

s s1;

sau đó trình biên dịch sẽ báo lỗi vì trong câu lệnh này s được coi là tên của mã định danh được khai báo ở trên. Để giải quyết sự mơ hồ, bạn cần sử dụng từ khóa struct

struct s
{
    int s;
};

s s;

struct s s1;

Điều này được mô tả trong trích dẫn sau đây từ Tiêu chuẩn C ++ 20 (6.3.1 Vùng và phạm vi khai báo)

4 Cho một tập hợp các khai báo trong một vùng khai báo, mỗi vùng chỉ định cùng một tên không đủ tiêu chuẩn,

(4.1) - tất cả chúng sẽ tham chiếu đến cùng một thực thể hoặc tất cả đều đề cập đến các hàm và mẫu hàm; hoặc là

(4.2) - chính xác một khai báo sẽ khai báo tên lớp hoặc tên liệt kê không phải là tên typedef và các khai báo khác đều tham chiếu đến cùng một biến, thành viên dữ liệu không tĩnh hoặc liệt kê hoặc tất cả đều đề cập đến các hàm và mẫu hàm ; trong trường hợp này, tên lớp hoặc tên liệt kê bị ẩn (6.3.10). [ Lưu ý: Tên không gian tên hoặc tên mẫu lớp phải là duy nhất trong vùng khai báo của nó (10.3.2, Khoản 17). - lưu ý cuối ]

Như bạn có thể thấy trong đoạn trích dẫn, một tên không gian tên phải là duy nhất trong vùng khai báo của nó. Vì vậy, những tuyên bố này

struct Foo { };
namespace Foo { } 

không chính xác

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.