Mengapa forward-mendeklarasikan diperlukan dalam C ++
Kompiler ingin memastikan Anda tidak membuat kesalahan pengejaan atau memberikan jumlah argumen yang salah ke fungsi. Jadi, ini menegaskan bahwa ia pertama kali melihat deklarasi 'add' (atau jenis, kelas, atau fungsi lainnya) sebelum digunakan.
Ini benar-benar hanya memungkinkan kompiler untuk melakukan pekerjaan yang lebih baik dalam memvalidasi kode, dan memungkinkannya untuk merapikan ujung yang longgar sehingga dapat menghasilkan file objek yang tampak rapi. Jika Anda tidak perlu meneruskan mendeklarasikan sesuatu, kompiler akan menghasilkan file objek yang harus berisi informasi tentang semua dugaan yang mungkin tentang apa fungsi 'add' mungkin. Dan linker harus mengandung logika yang sangat pintar untuk mencoba dan mencari tahu 'add' yang ingin Anda panggil, ketika fungsi 'add' dapat hidup dalam file objek yang berbeda, linker bergabung dengan yang menggunakan add untuk menghasilkan dll atau exe. Mungkin saja linker mendapatkan tambahan yang salah. Katakanlah Anda ingin menggunakan int add (int a, float b), tetapi tidak sengaja lupa untuk menuliskannya, tetapi linker menemukan int add yang sudah ada (int a, int b) dan berpikir itu yang benar dan menggunakannya. Kode Anda akan dikompilasi, tetapi tidak akan melakukan apa yang Anda harapkan.
Jadi, hanya untuk membuat hal-hal eksplisit dan menghindari tebakan dll, kompiler bersikeras Anda menyatakan semuanya sebelum digunakan.
Perbedaan antara deklarasi dan definisi
Selain itu, penting untuk mengetahui perbedaan antara deklarasi dan definisi. Deklarasi hanya memberikan kode yang cukup untuk menunjukkan seperti apa sesuatu itu, jadi untuk suatu fungsi, ini adalah tipe pengembalian, konvensi pemanggilan, nama metode, argumen dan tipenya. Tetapi kode untuk metode ini tidak diperlukan. Untuk sebuah definisi, Anda memerlukan deklarasi dan juga kode untuk fungsinya juga.
Bagaimana deklarasi maju dapat secara signifikan mengurangi waktu pembuatan
Anda bisa memasukkan deklarasi fungsi ke file .cpp atau .h Anda saat ini dengan # menyertakan header yang sudah berisi deklarasi fungsi. Namun, ini dapat memperlambat kompilasi Anda, terutama jika Anda # memasukkan header ke dalam .h alih-alih .cpp dari program Anda, karena segala sesuatu yang # termasuk .h yang sedang Anda tulis akan berakhir # termasuk semua header Anda menulis #termasuk juga. Tiba-tiba, kompiler memiliki #include halaman dan halaman kode yang perlu dikompilasi bahkan ketika Anda hanya ingin menggunakan satu atau dua fungsi. Untuk menghindari ini, Anda dapat menggunakan deklarasi maju dan cukup ketik sendiri deklarasi fungsi di bagian atas file. Jika Anda hanya menggunakan beberapa fungsi, ini benar-benar dapat membuat kompilasi Anda lebih cepat dibandingkan dengan selalu menyertakan header. Untuk proyek yang sangat besar,
Pecahkan referensi siklik di mana dua definisi saling menggunakan
Selain itu, deklarasi maju dapat membantu Anda memutus siklus. Di sinilah dua fungsi keduanya mencoba menggunakan satu sama lain. Ketika ini terjadi (dan ini adalah hal yang benar-benar sah untuk dilakukan), Anda dapat #mengikutsertakan satu file header, tetapi file header itu mencoba untuk #mengikutsertakan file header yang sedang Anda tulis .... yang kemudian #termasuk header lainnya , yang termasuk # yang Anda tulis. Anda terjebak dalam situasi ayam dan telur dengan masing-masing file header mencoba memasukkan # lainnya. Untuk mengatasi ini, Anda dapat meneruskan-mendeklarasikan bagian-bagian yang Anda butuhkan di salah satu file dan meninggalkan #sertakan dari file itu.
Misalnya:
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 ... deklarasi Mobil diperlukan di sini karena Wheel memiliki pointer ke Mobil, tetapi Car.h tidak dapat dimasukkan di sini karena akan menghasilkan kesalahan kompiler. Jika Car.h dimasukkan, maka akan mencoba untuk memasukkan Wheel.h yang akan mencakup Car.h yang akan mencakup Wheel.h dan ini akan berlangsung selamanya, jadi sebagai gantinya kompiler menimbulkan kesalahan. Solusinya adalah dengan meneruskan mendeklarasikan Mobil:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Jika Roda kelas memiliki metode yang perlu memanggil metode mobil, metode tersebut dapat didefinisikan dalam Wheel.cpp dan Wheel.cpp sekarang dapat memasukkan Car.h tanpa menyebabkan siklus.