2010-03-27 36 views
5

Sự khác biệt giữa hai khai báo sau đây là gì? Tôi nghĩ chúng tương đương nhau, nhưng mẫu đầu tiên hoạt động, và mẫu thứ hai thì không. Tôi có nghĩa là nó biên dịch và chạy, nhưng mã hiển thị bitmap hiển thị trống. Tôi chưa bước qua nó, nhưng tôi có thiếu cái gì đó hiển nhiên không? GUI_BITMAP là một cấu trúc đơn giản mô tả một bitmap. Điều này là dành cho VC + + 2005, nhưng tôi nghĩ rằng nó không thành công trong VC++ 2008. Gãi đầu của tôi trên một này ...Vấn đề với từ khóa bên ngoài trong C++

Mẫu 1:

extern "C" const GUI_BITMAP bmkeyA_cap_active; 
extern "C" const GUI_BITMAP bmkeyA_cap_inactive; 

Mẫu 2:

extern "C" 
{ 
    const GUI_BITMAP bmkeyA_cap_active; 
    const GUI_BITMAP bmkeyA_cap_inactive; 
}; 

Edit: More thăm dò đã cho thấy rằng ví dụ thứ hai là tạo ra các cấu trúc, trong khi đầu tiên là đề cập đến các cấu trúc bên ngoài. Ví dụ thứ hai sẽ không liên kết, vì có hai biến ở phạm vi toàn cục có cùng tên. Nhưng nó không, nó sẽ gửi một cấu trúc không đầy đến mã hiển thị mà từ bỏ. Hmmm .....

Chỉnh sửa 2: Chạy cùng một mã thông qua trình biên dịch khác (IAR) thực sự không biên dịch được trên Mẫu 2, với lỗi về thiếu hàm tạo mặc định. Vì vậy, tôi đoán có cái gì đó tinh tế về từ khóa "extern", cấu trúc, và C + + mà tôi không nhận được. Nếu những thứ trong khu vực bên ngoài có chức năng thì hai mẫu sẽ giống hệt nhau không?

Trả lời

3

Trình liên kết của bạn có thể đang âm thầm giải quyết các biểu tượng trùng lặp sau lưng bạn. Bạn có thể nhận được các thư viện tĩnh từ một nhà cung cấp và phải liên kết chúng với chương trình của bạn - giải pháp cho tình huống mà bạn có hai thư viện như vậy và cả hai đều xác định một biểu tượng chung là gì? Trình liên kết sẽ giải quyết vấn đề đó, chọn một hoặc một định nghĩa khác và để bạn giải quyết vấn đề này. Bạn xử lý giai đoạn liên kết của ứng dụng của bạn như thế nào? Bạn có thể có kết quả tốt hơn nếu bạn liên kết .o tệp trực tiếp thay vì đưa chúng vào thư viện trung gian trước khi liên kết ứng dụng cuối cùng.

This page của tài liệu ARM mô tả các vấn đề tốt - Tôi hy vọng hành vi tương tự đang xảy ra trong trường hợp của bạn:

Nhiều định nghĩa của một biểu tượng trong các đối tượng thư viện khác nhau không nhất thiết phải phát hiện. Một khi mối liên kết đã tìm thấy một định nghĩa phù hợp cho một biểu tượng, nó ngừng tìm kiếm những người khác. Giả sử đối tượng chứa biểu tượng trùng lặp không được tải vì các lý do khác, không có lỗi nào xảy ra. Điều này là có chủ ý và đặc biệt hữu ích trong một số trường hợp.

Chỉnh sửa: Tìm kiếm khác đã phát sinh sự cố này do vi phạm "One Definition Rule" và do đó trình biên dịch/trình liên kết không được yêu cầu thông báo cho bạn về sự cố. Điều đó làm cho câu hỏi của bạn trùng lặp với this one.

+0

Cảm ơn bạn đã trả lời, nhưng không có đối tượng thư viện nào được sử dụng ở đây, đây chỉ là mã của tôi, một hỗn hợp của C và C++. Câu hỏi ban đầu của tôi vẫn còn - sự khác biệt giữa Mẫu 1 và Mẫu 2 - Tôi nghĩ rằng họ nên tạo chính xác cùng một mã? Nếu mọi thứ là các hàm thay vì cấu trúc - chúng giống nhau, đúng không? – Jeff

+1

@ Jeff, câu trả lời nhanh cho câu hỏi của bạn là không, hai cái đó không giống nhau, đó là lý do tại sao bạn thấy vấn đề.Trong trường hợp thứ hai, bạn chỉ sửa đổi các câu lệnh bên trong '{}' để sử dụng các quy ước liên kết của C. Trong ví dụ đầu tiên, bạn đang làm điều đó * plus * chỉ ra rằng các biến được khai báo ở nơi khác. http://msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx –

0

Ví dụ thứ hai có thể tương đương với ví dụ thứ nhất có thêm một extern ở phía trước của const. Trong trường hợp đầu tiên, trình biên dịch có lẽ là kết hợp hai sử dụng của extern. Trong trường hợp thứ hai, tôi sẽ giả sử trình biên dịch không phải tất cả mọi thứ nam trong extern phạm vi extern cho bất cứ lý do gì.

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