Tại sao khai báo chuyển tiếp là cần thiết trong C ++
Trình biên dịch muốn đảm bảo bạn chưa mắc lỗi chính tả hoặc chuyển sai số lượng đối số cho hàm. Vì vậy, nó khẳng định rằng lần đầu tiên nó nhìn thấy một tuyên bố 'thêm' (hoặc bất kỳ loại, lớp hoặc hàm nào khác) 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 công việc xác thực mã tốt hơn và cho phép nó dọn dẹp các đầu lỏng để nó có thể tạo ra một tệp đối tượng trông 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 phải chứa thông tin về tất cả các dự đoán có thể 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 'add' mà bạn thực sự muốn gọi, khi chức năng 'add' có thể nằm 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 tệp sử dụng add để sản xuất một dll hoặc exe. Có thể là trình liên kết có thể nhận được 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 viết nó, nhưng trình liên kết đã tìm thấy một int add đã có sẵn (int a, int b) và nghĩ rằng đó là một cái đúng và sử dụng nó 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, vv, 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 biệt giữa khai báo và định nghĩa
Bên cạnh đó, đ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ị một cái gì đó trông như thế nào, vì vậy đối với một hàm, đây là kiểu trả về, gọi quy ước, tên phương thức, đối số và kiểu của chúng. Nhưng mã cho phương thức không bắt buộc. Đối với một định nghĩa, bạn cần khai báo và sau đó là mã cho hàm.
Làm thế nào khai báo chuyển tiếp có thể giảm đáng kể thời gian xây dựng
Bạn có thể lấy khai báo của hàm vào tệp .cpp hoặc .h hiện tại của mình bằng cách # bao gồm tiêu đề đã chứa khai báo của hàm. Tuy nhiên, điều này có thể làm chậm quá trình biên dịch của bạn, đặc biệt nếu bạn # bao gồm một tiêu đề thành .h thay vì .cpp của chương trình của bạn, vì mọi thứ bao gồm .h bạn đang viết sẽ kết thúc # bao gồm tất cả các tiêu đề bạn đã viết #incoles cho quá. Đột nhiên, trình biên dịch 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 khai báo chuyển tiếp và chỉ cần tự khai báo hàm ở đầu tệp. Nếu bạn chỉ sử dụng một vài chức năng, điều này thực sự có thể làm cho trình biên dịch của bạn nhanh hơn so với việc luôn luôn bao gồm tiêu đề. Đối với các dự án thực sự lớn,
Phá vỡ các tham chiếu theo chu kỳ trong đó hai định nghĩa đều sử dụng lẫn nhau
Ngoài ra, khai báo chuyển tiếp có thể giúp bạn phá vỡ các chu kỳ. Đây là nơi hai chức năng cả hai cố gắng sử dụng lẫn nhau. Khi điều này xảy ra (và đó là một điều hoàn toàn hợp lệ để làm), bạn có thể #inc loại trừ một tệp tiêu đề, nhưng tệp tiêu đề đó cố gắng #inc loại trừ tệp tiêu đề bạn hiện đang viết .... sau đó loại bỏ tiêu đề khác , trong đó bao gồm những gì bạn đang viết. Bạn đang bị mắc kẹt trong tình huống gà và trứng với mỗi tệp tiêu đề đang cố gắng loại bỏ lại cái 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à loại bỏ #incolee khỏi tệp đó.
Ví dụ:
Hồ sơ xe.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
Hồ sơ bánh xe.h
Hmm ... việc khai báo Xe hơi được yêu cầu ở đây vì Wheel có con trỏ tới Xe hơi, nhưng Car.h không thể được đưa vào đây vì nó sẽ dẫn đến lỗi trình biên dịch. Nếu Car.h được bao gồm, thì điều đó sẽ cố gắng bao gồm Wheel.h sẽ bao gồm Car.h sẽ bao gồm Wheel.h và điều này sẽ tiếp diễn mãi mãi, vì vậy thay vào đó trình biên dịch sẽ phát sinh lỗi. Giải pháp là chuyển tiếp khai báo Xe thay thế:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Nếu lớp Wheel có các phương thức cần gọi các phương thức của ô tô, các phương thức đó có thể được định nghĩa trong Wheel.cpp và Wheel.cpp hiện có thể bao gồm Car.h mà không gây ra chu kỳ.