Đầu tiên, để giải quyết yêu cầu đầu tiên của bạn:
Khi bạn thấy điều này trong tệp .h :
#ifndef FILE_H
#define FILE_H
/* ... Declarations etc here ... */
#endif
Đây là một kỹ thuật tiền xử lý để ngăn chặn tệp tiêu đề được đưa vào nhiều lần, có thể gây ra sự cố vì nhiều lý do. Trong quá trình biên dịch dự án của bạn, mỗi tệp .cpp (thường) được biên dịch. Nói một cách đơn giản, điều này có nghĩa là trình biên dịch sẽ lấy tệp .cpp của bạn , mở bất kỳ tệp nào #included
bằng cách đó, ghép tất cả chúng thành một tệp văn bản lớn và sau đó thực hiện phân tích cú pháp và cuối cùng nó sẽ chuyển đổi nó thành một số mã trung gian, tối ưu hóa / thực hiện khác các tác vụ và cuối cùng tạo ra đầu ra lắp ráp cho kiến trúc đích. Bởi vì điều này, nếu một tệp #included
nhiều lần dưới một .cpptệp, trình biên dịch sẽ nối thêm nội dung tệp của nó hai lần, vì vậy nếu có các định nghĩa trong tệp đó, bạn sẽ gặp lỗi trình biên dịch cho bạn biết rằng bạn đã xác định lại một biến. Khi tệp được xử lý bởi bước tiền xử lý trong quá trình biên dịch, lần đầu tiên nội dung của nó đạt được hai dòng đầu tiên sẽ kiểm tra xem FILE_H
đã được xác định cho bộ tiền xử lý chưa. Nếu không, nó sẽ định nghĩa FILE_H
và tiếp tục xử lý mã giữa nó và lệnh #endif
. Lần tiếp theo nội dung của tập tin được xem bởi bộ xử lý, kiểm tra chống lại FILE_H
sẽ là sai, vì vậy nó sẽ ngay lập tức quét xuống #endif
và tiếp tục sau đó. Điều này ngăn ngừa lỗi xác định lại.
Và để giải quyết mối quan tâm thứ hai của bạn:
Trong lập trình C ++ như một thông lệ chung, chúng tôi tách phát triển thành hai loại tệp. Một là với phần mở rộng là .h và chúng tôi gọi đây là "tệp tiêu đề." Chúng thường cung cấp một khai báo các hàm, lớp, cấu trúc, biến toàn cục, typedefs, macro tiền xử lý và định nghĩa, v.v. Về cơ bản, chúng chỉ cung cấp cho bạn thông tin về mã của bạn. Sau đó, chúng tôi có phần mở rộng .cpp mà chúng tôi gọi là "tệp mã." Điều này sẽ cung cấp các định nghĩa cho các hàm đó, các thành viên lớp, bất kỳ thành viên cấu trúc nào cần định nghĩa, biến toàn cục, v.v. Vì vậy, tệp .h khai báo mã và tệp .cpp thực hiện khai báo đó. Vì lý do này, chúng tôi thường trong quá trình biên dịch biên dịch từng .cpptệp vào một đối tượng và sau đó liên kết các đối tượng đó (vì bạn hầu như không bao giờ thấy một tệp .cpp bao gồm tệp .cpp khác ).
Làm thế nào những giải pháp bên ngoài này được giải quyết là một công việc cho trình liên kết. Khi trình biên dịch của bạn xử lý main.cpp , nó sẽ nhận được các khai báo cho mã trong class.cpp bằng cách bao gồm class.h . Nó chỉ cần biết các hàm hoặc biến này trông như thế nào (đó là những gì một khai báo mang lại cho bạn). Vì vậy, nó biên dịch tệp main.cpp của bạn thành một số tệp đối tượng (gọi nó là main.obj ). Tương tự, class.cpp được biên dịch thành class.objtập tin. Để tạo ra tệp thực thi cuối cùng, một trình liên kết được gọi để liên kết hai tệp đối tượng đó với nhau. Đối với bất kỳ biến hoặc hàm bên ngoài chưa được giải quyết, trình biên dịch sẽ đặt một sơ khai nơi truy cập xảy ra. Sau đó, trình liên kết sẽ lấy sơ khai này và tìm mã hoặc biến trong tệp đối tượng được liệt kê khác và nếu tìm thấy, nó kết hợp mã từ hai tệp đối tượng thành tệp đầu ra và thay thế sơ khai bằng vị trí cuối cùng của hàm hoặc Biến đổi. Bằng cách này, mã của bạn trong main.cpp có thể gọi các hàm và sử dụng các biến trong class.cpp NẾU VÀ CHỈ NẾU NẾU ĐƯỢC GIẢI QUYẾT TRONG class.h .
Tôi hy vọng nó sẽ có ích.