2012-12-18 38 views
6

Tôi đã ấn tượng rằng C++ áp dụng cùng một quy tắc đặc biệt cho một loại static const tách rời bất kể cho dù khai báo ở phạm vi không gian tên hoặc khai báo trong lớp/struct/union.C++ áp dụng các quy tắc đặc biệt nào cho các loại tích phân const tĩnh?

Bây giờ tôi nghĩ rằng tôi đã được dạy những điều tồi tệ bởi các trình biên dịch không tuân thủ.

static const int A = 1; 

struct s 
{ 
    static const int A = 1; 
}; 

Bên cạnh sự khác biệt rõ ràng trong phạm vi, Làm thế nào để As::A khác nhau?

  • ... khi nào việc sử dụng của chúng sẽ được thay thế bằng giá trị bằng chữ?
  • ... khi tôi có thể lấy địa chỉ của nó?
  • ... khi tôi cần xác định riêng chúng?

tôi tò mò đặc biệt về C++ 03.

+0

Tại sao bạn nghĩ có sự khác biệt? Điều trị đặc biệt là chúng có thể được coi là biểu thức không đổi. Đừng nghĩ về "thay thế bằng giá trị chữ". – Pubby

+1

@Pubby Hãy thử 'const int & x = s :: A;' sau đó, và sử dụng 'x' ở đâu đó. Rất có thể bạn sẽ gặp lỗi liên kết. – hvd

Trả lời

6

Từ khóa static không có nghĩa là điều tương tự trong phạm vi lớp và trong phạm vi không gian tên. Thực tế, việc sử dụng nó trong phạm vi không gian tên là không được chấp nhận.

Khi khai báo biến ở phạm vi lớp học, static có nghĩa là sẽ có một phiên bản duy nhất của biến, với thời lượng lưu trữ và tuổi thọ tĩnh . Tuyên bố trong lớp là không phải định nghĩa; nếu biến là sử dụng, thì phải là được xác định trong một (và chỉ một) đơn vị dịch; nếu nó không được xác định là , bạn có hành vi không xác định. (Trong thực tế, tùy thuộc vào về việc sử dụng, mọi thứ sẽ hoạt động tốt, hoặc bạn sẽ gặp lỗi từ trình liên kết.) Lưu ý rằng nếu khai báo là loại tích phân const và chứa khởi tạo, đó là không được coi là được sử dụng nếu nó được sử dụng trong ngữ cảnh yêu cầu một biểu thức tích phân không đổi (như kích thước của một kiểu C kiểu C). Điều đơn giản và chắc chắn nhất là chỉ định nghĩa nó ở đâu đó.

Khi khai báo biến tại phạm vi không gian tên, static có nghĩa là rằng tên có liên kết nội bộ, thay vì bên ngoài; với hoặc không có static, tuyên bố là định nghĩa (do đó, có không được định nghĩa khác trong chương trình). Trong C++ 03, việc sử dụng này không được chấp nhận; sử dụng không gian tên chưa đặt tên thay thế. Lưu ý quá nếu biến đó là const (const cấp cao nhất), thì nó có liên kết nội bộ theo mặc định, do đó, static không có hiệu ứng nào. (Nếu bạn cần một biến const với liên kết bên ngoài, làm cho nó một thành viên lớp, hoặc định nghĩa nó rõ ràng extern, sử dụng một initializer để làm cho nó một định nghĩa, chứ không phải chỉ là một tuyên bố.)

+0

Cần lưu ý rằng tĩnh tại phạm vi không gian tên không còn bị phản đối trong C++ 11 do đó không cần phải tránh sử dụng nó vì lợi ích của việc kiểm chứng trong tương lai. – John5342

+0

@ John5342 Tôi nghĩ tôi đã nghe điều gì đó dọc theo những dòng đó. Nghe có vẻ hơi mơ hồ với tôi: không được chấp nhận, sau đó không được chấp nhận. Điều tiếp theo chúng ta biết, chúng sẽ khôi phục 'export' và' std :: auto_ptr'. –

+0

Nó không được chấp nhận bởi vì nó có một số tác dụng phụ lạ (tôi không thể tìm thấy liên kết tại thời điểm này) và không gian tên không tên được cung cấp một thay thế được cho là tốt hơn. Sau đó đã có nhiều khiếu nại rằng các không gian tên không được đặt tên đã không cung cấp một sự lựa chọn hoàn toàn có thể chấp nhận được và do đó nó không được chấp nhận. Một số người sẽ thấy nó như mơ hồ. Những người khác sẽ gọi nó là lắng nghe người dùng của nó và làm điều đúng ngay cả khi nó có nghĩa là backtracking một chút. – John5342

0

thế nào As::A khác nhau?

Sự khác biệt lớn nhất là việc khai báo A cũng là định nghĩa, trong khi đó s::A thì không. Tôi không chắc chắn ý của bạn là "quy tắc đặc biệt", nhưng static có ý nghĩa khác trong mỗi trường hợp.

Ở phạm vi không gian tên, nó cung cấp cho nó liên kết nội bộ để đối tượng không hiển thị bên ngoài đơn vị dịch hiện tại. Lưu ý rằng static là dư thừa ở đây, vì các biến không đổi ở phạm vi không gian tên có liên kết nội bộ theo mặc định.

Ở phạm vi lớp học, điều đó có nghĩa là có một đối tượng độc lập với bất kỳ phiên âm nào của lớp.

khi sử dụng của chúng sẽ được thay thế bằng giá trị bằng chữ?

Vì cả hai đều là hằng số không thể tách rời với bộ khởi tạo trong khai báo, cả hai có thể được sử dụng trong biểu thức không đổi và trình biên dịch có thể thay thế giá trị của chúng bằng hằng số biên dịch.

Có lẽ câu hỏi phù hợp hơn là khi nào một định nghĩa được yêu cầu?

Trong C++ 11, bắt buộc nếu biến là odr-sử dụng - gần như nói, nếu bạn làm bất cứ điều gì yêu cầu địa chỉ của biến thay vì giá trị của nó.

Trong C++ 03, tôi nghĩ rằng nó được yêu cầu nếu biến được sử dụng, mặc dù không cần chẩn đoán và nhiều trình biên dịch sẽ không phàn nàn nếu bạn chỉ sử dụng giá trị của nó. Tôi có thể sai mặc dù; các quy tắc cũ khá phức tạp và tôi rất vui khi có thể quên chúng ngay bây giờ.

khi tôi có thể lấy địa chỉ của nó?

Điều đó yêu cầu biến phải có định nghĩa, trong cả C++ 03 và C++ 11. Định nghĩa phân bổ lưu trữ cho biến, sao cho nó có địa chỉ.

khi tôi cần xác định riêng chúng?

Tuyên bố biến tại phạm vi không gian tên cũng là định nghĩa, trừ khi bạn khai báo nó extern; do đó, biến đầu tiên của bạn không cần định nghĩa riêng.

Tuyên bố biến ở phạm vi lớp học không phải là định nghĩa; vì vậy biến thứ hai của bạn không cần định nghĩa riêng trong C++ 03 và trong C++ 11 nếu nó là odr-used.

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