2012-04-20 53 views
8

Tôi luôn gặp lỗi khi cố gắng xác định hàm C trong tệp tiêu đề ngay phía trên giao diện của lớp.Tại sao tôi không thể định nghĩa các hàm C thuần túy trong tệp tiêu đề?

nhưng khi tôi làm như vậy trong tệp triển khai và đưa ra tuyên bố trong tiêu đề. Mọi việc diễn ra.

Tôi muốn biết, tại sao nó như vậy vì tôi đã xác định enums, cấu trúc, liên tục NSStrings trong tập tin tiêu đề, vậy tại sao không C chức năng?

Trả lời

14

Điều này phù hợp với cách mà trình liên kết C (hoặc trình chỉnh sửa liên kết) hoạt động. Khi trình biên dịch C đi qua một định nghĩa hàm, nó chuẩn bị mã trình lắp ráp thực hiện chức năng đó và đánh dấu nó bằng một biểu tượng nói với trình liên kết "đây là nơi hàm bắt đầu với hàm này". Biểu tượng thường được đặt tên với dấu gạch dưới theo sau là tên hàm, ví dụ: _printf.

Nếu bạn xác định hàm trong tệp tiêu đề, thì mỗi tệp .c hoặc .m nhập tiêu đề này sẽ biên dịch hàm và sẽ làm cho trình biên dịch phát ra cùng biểu tượng. Trình liên kết hy vọng sẽ chỉ tìm thấy một cá thể của mỗi biểu tượng, vì vậy đây là lỗi.

Điều này không liên quan đến sự tồn tại của bảo vệ #include hoặc sử dụng #import thay vì #include. Trình biên dịch C hoạt động trên các đơn vị dịch riêng lẻ - theo đó nó có nghĩa là các tệp nguồn riêng lẻ. Các chiến lược tiền xử lý ngăn bạn bao gồm cùng một tệp tiêu đề hai lần vào một tệp nguồn duy nhất, nhưng không làm gì để phối hợp các hoạt động trên nhiều tệp. Điều đó có nghĩa là nó hợp lệ để bao gồm cùng một tiêu đề trong các tệp nguồn khác nhau: nó cũng có nghĩa là khi bạn biên dịch các tệp khác nhau, chúng có thể (hợp pháp) chứa cùng một biểu tượng.

Đó là công việc của trình chỉnh sửa liên kết để đặt các tệp này lại với nhau, giải quyết mọi tham chiếu đến các biểu tượng không xác định tại thời gian biên dịch. Nếu bạn cố gắng liên kết các đối tượng (tên của các đơn vị biên dịch đã được biên soạn và lắp ráp) có cùng biểu tượng trong cùng một kho lưu trữ, thư viện được chia sẻ hoặc thực thi, thì bạn sẽ gặp lỗi bạn đang thấy ở đây.

Giải pháp:

  • Đừng xác định các chức năng trong phần đầu, chỉ cần khai báo nó ở đó và định nghĩa nó trong một tập tin thực hiện; như bạn đã tìm thấy công trình này.
  • Xác định chức năng trong tiêu đề, nhưng chỉ bao gồm tiêu đề đó ở một nơi trong mã của bạn. Điều này thường không thể chấp nhận được vì lý do thiết kế.
  • Xác định hàm trong tiêu đề bằng công cụ sửa đổi inline. Các hàm nội tuyến chỉ được sao chép bởi trình biên dịch vào hàm mà chúng được gọi, vì vậy một biểu tượng liên kết không bao giờ được phát ra cho chúng. Điều này có các giao dịch riêng của mình mà bạn may wish to read more about.
+0

shuldn't #import (thay vì #include) chỉ bao gồm một tệp? Và .. bạn cũng có thể sử dụng bao gồm bảo vệ (#ifndef MYFILE_H # define MYFILE_H ... #endif) – Francesco

+1

Cảm ơn câu hỏi @Francesco, tôi đã kết hợp câu trả lời ở trên (phiên bản ngắn gọn là các nhân viên tiền xử lý sẽ không dừng lại bạn nhận được lỗi liên kết). –

+0

Nhưng .. chúng ta đang nói về các định nghĩa hoặc khai báo của các hàm C? Bởi vì .. Tôi đã thử với định nghĩa hàm trong tệp .h và bao gồm hai lần tệp. Nếu tôi sử dụng #include tôi nhận được "định nghĩa lại" chức năng. Nếu tôi sử dụng #import hoặc bảo vệ (trong mọi tệp .h), tôi sẽ không nhận được lỗi nào ... – Francesco

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