Tại sao phía trước-khai báo là cần thiết trong C++
Trình biên dịch muốn đảm bảo bạn chưa thực hiện lỗi chính tả hoặc thông qua sai số lập luận cho hàm. Vì vậy, nó khẳng định rằng nó lần đầu tiên nhìn thấy một tuyên bố của 'thêm' (hoặc bất kỳ loại nào khác, các lớp hoặc chức năng) trước khi nó được sử dụng. Điều này thực sự chỉ cho phép trình biên dịch thực hiện một công việc tốt hơn để xác nhận mã, và cho phép nó dọn dẹp các đầu lỏng lẻo để nó có thể tạo ra một tệp đối tượng tìm kiếm gọn gàng. Nếu bạn không phải chuyển tiếp khai báo mọi thứ, trình biên dịch sẽ tạo ra một tệp đối tượng có thể chứa thông tin về tất cả các dự đoán có thể có về chức năng 'thêm' có thể là gì. Và trình liên kết sẽ phải chứa logic rất thông minh để thử và tìm ra 'thêm' bạn thực sự muốn gọi, khi hàm 'thêm' có thể tồn tại trong một tệp đối tượng khác mà trình liên kết đang kết hợp với một trình sử dụng thêm để tạo một dll hoặc exe. Có thể người liên kết có thể bị thêm sai. Giả sử bạn muốn sử dụng int add (int a, float b), nhưng vô tình quên ghi nó, nhưng linker tìm thấy một int đã có sẵn (int a, int b) và nghĩ rằng đó là một trong những quyền và được sử dụng để thay thế. Mã của bạn sẽ biên dịch, nhưng sẽ không làm những gì bạn mong đợi.
Vì vậy, chỉ để giữ cho mọi thứ rõ ràng và tránh đoán, trình biên dịch khẳng định bạn khai báo mọi thứ trước khi nó được sử dụng.
Sự khác nhau giữa khai báo và định nghĩa
Là một sang một bên, điều quan trọng là phải biết sự khác biệt giữa một tuyên bố và một định nghĩa. Một khai báo chỉ cung cấp đủ mã để hiển thị cái gì đó trông giống như vậy, vì vậy đối với một hàm, đây là kiểu trả về, quy ước gọi, tên phương thức, các đối số và các kiểu của chúng. Nhưng mã cho phương pháp này là không cần thiết. Đối với một định nghĩa, bạn cần khai báo và sau đó cũng là mã cho hàm đó.
Làm thế nào phía trước-tờ khai có thể làm giảm đáng kể xây dựng lần
Bạn có thể nhận tờ khai của một hàm thành cpp hiện tại của bạn hoặc file .h bởi # includ'ing header đã có chứa một tuyên bố của chức năng. Tuy nhiên, điều này có thể làm chậm biên dịch của bạn, đặc biệt nếu bạn #bao gồm một tiêu đề vào một .h thay vì .cpp của chương trình của bạn, vì mọi thứ mà #includes .h bạn đang viết sẽ kết thúC# include'ing tất cả các tiêu đề bạn đã viết #includes cho quá. Đột nhiên, trình biên dịch có #included các trang và các trang mã mà nó cần biên dịch ngay cả khi bạn chỉ muốn sử dụng một hoặc hai hàm. Để tránh điều này, bạn có thể sử dụng một tuyên bố chuyển tiếp và chỉ cần gõ vào khai báo của hàm mình ở đầu tệp. Nếu bạn chỉ sử dụng một vài hàm, điều này thực sự có thể làm cho việc biên dịch của bạn nhanh hơn so với luôn luôn # bao gồm tiêu đề. Đối với các dự án thực sự lớn, sự khác biệt có thể là một giờ hoặc nhiều hơn thời gian biên dịch mua xuống một vài phút.
Nghỉ tài liệu tham khảo cyclic nơi hai định nghĩa đều sử dụng nhau
Bên cạnh đó, về phía trước-tờ khai có thể giúp bạn phá vỡ chu kỳ. Đây là nơi hai chức năng cố gắng sử dụng lẫn nhau. Khi điều này xảy ra (và đó là điều hoàn toàn hợp lệ để làm), bạn có thể #include một tệp tiêu đề, nhưng tệp tiêu đề đó cố gắng #include tệp tiêu đề bạn hiện đang viết .... sau đó #includes tiêu đề khác , bao gồm # bạn đang viết. Bạn đang mắc kẹt trong một tình huống gà và trứng với mỗi tập tin tiêu đề cố gắng để lại # bao gồm khác. Để giải quyết vấn đề này, bạn có thể chuyển tiếp khai báo các phần bạn cần trong một trong các tệp và để #include ra khỏi tệp đó.
Ví dụ:
file Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
file Wheel.h
Hmm ... việc kê khai của xe là cần thiết ở đây là bánh xe có một con trỏ đến một chiếc xe, nhưng Car.h không thể được bao gồm ở đây vì nó sẽ dẫn đến một lỗi trình biên dịch. Nếu Car.h được bao gồm, sau đó sẽ cố gắng bao gồm Wheel.h trong đó bao gồm Car.h mà sẽ bao gồm Wheel.h và điều này sẽ đi mãi mãi, vì vậy thay vào đó trình biên dịch đưa ra một lỗi. Giải pháp là để chuyển tiếp khai báo xe thay vì:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Nếu lớp Wheel đã phương pháp mà cần phải gọi các phương thức của xe, các phương pháp đó có thể được quy định tại Wheel.cpp và Wheel.cpp giờ đây có thể bao gồm Car.h mà không gây ra chu kỳ.
A "về phía trước tuyên bố" thực sự chỉ là một tuyên bố. Xem (kết thúc) câu trả lời này: http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration/1410632#1410632 – sbi