เหตุใดจึงจำเป็นต้องมีการประกาศล่วงหน้าใน C ++
คอมไพเลอร์ต้องการให้แน่ใจว่าคุณยังไม่ได้สะกดคำผิดหรือส่งจำนวนอาร์กิวเมนต์ที่ไม่ถูกต้องไปยังฟังก์ชัน ดังนั้นจึงยืนยันว่าจะเห็นการประกาศของ 'เพิ่ม' (หรือประเภทอื่น ๆ คลาสหรือฟังก์ชั่น) ก่อนที่มันจะถูกนำมาใช้
นี่เป็นเพียงการอนุญาตให้คอมไพเลอร์ทำงานได้ดีขึ้นในการตรวจสอบความถูกต้องของรหัสและอนุญาตให้มันเป็นระเบียบเรียบร้อยหมดสิ้นเพื่อให้สามารถสร้างไฟล์วัตถุที่ดูเรียบร้อย หากคุณไม่จำเป็นต้องส่งต่อสิ่งต่าง ๆ คอมไพเลอร์จะสร้างออบเจ็กต์ไฟล์ที่จะต้องมีข้อมูลเกี่ยวกับการเดาที่เป็นไปได้ทั้งหมดว่าฟังก์ชัน 'เพิ่ม' อาจเป็นอะไร และตัวเชื่อมโยงจะต้องมีตรรกะที่ฉลาดมากเพื่อลองใช้งาน 'เพิ่ม' ที่คุณตั้งใจจะโทรจริงๆเมื่อฟังก์ชั่น 'เพิ่ม' อาจมีชีวิตอยู่ในไฟล์วัตถุที่แตกต่างกัน dll หรือ exe เป็นไปได้ว่าตัวเชื่อมโยงอาจได้รับการเพิ่มผิด สมมติว่าคุณต้องการใช้ int add (int a, float b) แต่บังเอิญลืมที่จะเขียนมัน แต่ linker พบ int ที่มีอยู่แล้วเพิ่ม (int a, int b) และคิดว่าเป็นสิ่งที่ถูกต้องและใช้สิ่งนั้นแทน รหัสของคุณจะรวบรวม แต่จะไม่ทำสิ่งที่คุณคาดหวัง
ดังนั้นเพื่อให้สิ่งต่าง ๆ ชัดเจนและหลีกเลี่ยงการเดา ฯลฯ คอมไพเลอร์ยืนยันว่าคุณประกาศทุกอย่างก่อนที่มันจะถูกนำมาใช้
ความแตกต่างระหว่างการประกาศและคำจำกัดความ
เป็นเรื่องสำคัญที่จะต้องทราบความแตกต่างระหว่างการประกาศและคำจำกัดความ การประกาศให้รหัสเพียงพอที่จะแสดงสิ่งที่ดูเหมือนดังนั้นสำหรับฟังก์ชั่นนี้เป็นประเภทกลับมาประชุมเรียกชื่อวิธีการข้อโต้แย้งและประเภทของพวกเขา แต่ไม่จำเป็นต้องใช้รหัสสำหรับวิธีการ สำหรับคำนิยามคุณต้องมีการประกาศแล้วก็รหัสสำหรับฟังก์ชั่นด้วย
วิธีการประกาศล่วงหน้าสามารถลดเวลาสร้างได้อย่างมาก
คุณสามารถรับฟังก์ชั่นการประกาศลงในไฟล์. cpp หรือ. h ปัจจุบันของคุณโดย # รวมถึงส่วนหัวที่มีการประกาศฟังก์ชัน อย่างไรก็ตามการทำเช่นนี้อาจทำให้การคอมไพล์ของคุณช้าลงโดยเฉพาะอย่างยิ่งหากคุณรวมส่วนหัวเป็น. h แทนที่จะเป็น. cpp ของโปรแกรมของคุณเนื่องจากทุกอย่างที่ # รวมถึง. h ที่คุณเขียนจะลงท้ายด้วย # รวมถึงส่วนหัวทั้งหมด คุณได้เขียน #includes ไว้ด้วย ทันใดนั้นคอมไพเลอร์ก็มีหน้า #included และหน้าของรหัสที่จำเป็นต้องรวบรวมแม้เมื่อคุณต้องการใช้เพียงหนึ่งหรือสองฟังก์ชั่น เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถใช้การประกาศไปข้างหน้าและพิมพ์การประกาศของฟังก์ชันเองที่ด้านบนของไฟล์ หากคุณใช้ฟังก์ชั่นเพียงไม่กี่ฟังก์ชั่นนี้จะทำให้คอมไพล์ของคุณเร็วขึ้นเทียบกับ #including ส่วนหัวเสมอ สำหรับโครงการขนาดใหญ่จริงๆ
ทำลายการอ้างอิงแบบวงกลมโดยที่ทั้งสองคำจำกัดความใช้กัน
นอกจากนี้การส่งต่อการประกาศสามารถช่วยคุณแบ่งวงจร นี่คือที่ที่ทั้งสองฟังก์ชั่นพยายามใช้ซึ่งกันและกัน เมื่อสิ่งนี้เกิดขึ้น (และเป็นสิ่งที่ถูกต้องสมบูรณ์แบบที่จะต้องทำ) คุณอาจ # รวมไฟล์ส่วนหัวหนึ่งไฟล์ แต่ไฟล์ส่วนหัวนั้นพยายามที่จะรวม # ไฟล์ส่วนหัวที่คุณกำลังเขียนอยู่ .... ซึ่ง #includes ส่วนหัวอื่น ๆ ซึ่งรวมถึงสิ่งที่คุณกำลังเขียน คุณติดอยู่ในสถานการณ์ไก่และไข่โดยที่ไฟล์ส่วนหัวแต่ละไฟล์พยายามที่จะรวมอีกครั้ง ในการแก้ปัญหานี้คุณสามารถส่งต่อชิ้นส่วนที่คุณต้องการในไฟล์ใดไฟล์หนึ่งและปล่อย #include ออกจากไฟล์นั้น
เช่น:
ไฟล์ Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
ไฟล์ Wheel.h
อืม ... ต้องมีการประกาศ Car ที่นี่เนื่องจาก Wheel มีตัวชี้ไปที่รถ แต่ Car.h ไม่สามารถรวมที่นี่ได้เพราะจะทำให้เกิดข้อผิดพลาดในการคอมไพเลอร์ หากมี Car.h รวมอยู่นั่นก็จะพยายามรวม Wheel.h ซึ่งจะรวม Car.h ซึ่งจะรวม Wheel.h และสิ่งนี้จะดำเนินต่อไปตลอดกาลดังนั้นคอมไพเลอร์จะทำให้เกิดข้อผิดพลาดแทน วิธีแก้ปัญหาคือการส่งต่อประกาศรถยนต์แทน:
class Car; // forward declaration
class Wheel
{
Car* car;
};
หากคลาสล้อมีวิธีที่จำเป็นต้องเรียกใช้วิธีการของรถยนต์วิธีเหล่านั้นสามารถกำหนดได้ใน Wheel.cpp และ Wheel.cpp สามารถรวม Car.h ได้โดยไม่ทำให้เกิดรอบ