2009-11-07 37 views
11

Tôi gặp sự cố khi khởi tạo một mảng có kích thước được định nghĩa là extern const. Tôi luôn tuân thủ quy tắc rằng các biến toàn cầu phải được khai báo là extern trong các tệp tiêu đề và các định nghĩa tương ứng của chúng phải nằm trong một trong các tệp triển khai để tránh các lỗi tái định nghĩa biến. Cách tiếp cận này làm việc tốt cho đến khi tôi đã phải khởi tạo một mảng với kích thước của nó được định nghĩa là một const bên ngoài. Tôi gặp lỗi khi biểu thức liên tục được mong đợi. Tuy nhiên, nếu tôi cố gắng gán một giá trị cho biến const thì trình biên dịch chính xác phàn nàn rằng một giá trị không thể được gán cho một biến không đổi. Điều này thực sự chứng minh rằng trình biên dịch không thấy biến là hằng số. Tại sao sau đó là một lỗi được báo cáo khi tôi cố gắng khai báo một mảng có cùng kích thước?Khai báo một mảng có kích thước được khai báo là extern const

Có cách nào để tránh điều này mà không sử dụng # define không? Tôi cũng muốn biết lý do cho lỗi này.

Package.h:

#ifndef PACKAGE_H 
#define PACKAGE_H 

extern const int SIZE; 

#endif 

Package.cpp:

#include "Package.h" 

const int SIZE = 10; 

Foo.cpp:

#include "Package.h" 

int main() 
{ 
    // SIZE = 5; // error - cannot assign value to a constant variable 
    // int Array[SIZE]; // error - constant expression expected 
    return 0; 
} 
+0

Bạn có thể thụt lề mã với bốn dấu cách để định dạng. – Thomas

Trả lời

16

Hằng số là bên ngoài, do đó nó được xác định trong một đơn vị biên dịch khác (.o tệp). Do đó trình biên dịch không thể xác định kích thước của mảng của bạn tại thời gian biên dịch; nó không được biết cho đến khi liên kết thời gian những gì giá trị của hằng số sẽ được.

3

Vâng, nó thấy các biến như const đủ điều kiện, không dưới dạng một biểu thức không đổi.

2

Tôi tin rằng vấn đề ở đây là nếu bạn khai báo biến là extern, nó được phép ở trong một mô-đun khác (.o) hoặc thậm chí trong thư viện động (.dll/.so). Điều này tất nhiên có nghĩa là, trình biên dịch có thể không có khả năng giải quyết nội dung biến tại thời gian biên dịch do đó từ chối sử dụng giá trị trong đó một const là bắt buộc.

Ý kiến ​​của tôi là hoàn toàn không được sử dụng extern ở đây và khai báo trực tiếp trong tệp tiêu đề vì nó là giá trị int sẽ được gạch chân khi được sử dụng ở bất kỳ đâu trong mã. Tôi thường sử dụng extern const chỉ khi làm việc với các chuỗi, vì tôi muốn đảm bảo rằng chỉ có một thể hiện của chuỗi được tạo ra khi chạy.

3

Vì đó chỉ là một int Tôi sẽ xóa extern và biến nó thành định nghĩa chứ không phải là tuyên bố. Lý do tôi nói điều này là mặc dù cách tiếp cận này đặt một trường hợp riêng biệt của số nguyên trong mỗi tệp nguồn bao gồm tiêu đề tôi sẽ tưởng tượng rằng hầu hết các trình biên dịch sẽ tối ưu hóa việc sử dụng nó. Trong thực tế nó không thể cho trình biên dịch để tối ưu hóa việc sử dụng nó nếu bạn không như vậy nó sẽ không được tối ưu hóa từ các biểu thức số học đơn giản.

Vì nó được khai báo const, nó sẽ có liên kết nội bộ và do đó bạn sẽ không nhận được bất kỳ vấn đề biểu tượng được định nghĩa nhân nào bằng cách thực hiện theo cách này.

+0

Cảm ơn. Tôi nghĩ tôi đã hiểu rồi. Nhưng, tại sao cách tiếp cận này không làm việc cho các con trỏ const. Nếu tôi định nghĩa const char * FILE_NAME = "Log.txt" trong tệp tiêu đề và bao gồm tệp tiêu đề trong nhiều tệp nguồn, tôi vẫn gặp lỗi liên kết. Tôi không gặp lỗi cho câu lệnh const char FILE_NAME [] = "Nhật ký.txt " – psvaibhav

+0

@psvaibhav: Điều đó sẽ không hoạt động vì' const char * 'khai báo con trỏ là một con trỏ trỏ tới const và _not_ là một con trỏ liên tục.Những gì bạn cần là một' const' thêm sau '*' để tạo con trỏ chính nó liên tục tức là 'const char * const' – Troubadour

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