Meskipun Anda dapat memasukkan .cpp
file seperti yang Anda sebutkan, ini adalah ide yang buruk.
Seperti yang Anda sebutkan, deklarasi termasuk dalam file header. Ini tidak menyebabkan masalah ketika dimasukkan dalam beberapa unit kompilasi karena mereka tidak menyertakan implementasi. Menyertakan definisi fungsi atau anggota kelas beberapa kali biasanya akan menyebabkan masalah (tetapi tidak selalu) karena linker akan menjadi bingung dan melempar kesalahan.
Apa yang harus terjadi adalah setiap .cpp
file menyertakan definisi untuk subset dari program, seperti kelas, kelompok fungsi yang diatur secara logis, variabel statis global (gunakan hemat jika sama sekali), dll.
Setiap unit kompilasi ( .cpp
file) kemudian menyertakan deklarasi apa pun yang diperlukan untuk mengkompilasi definisi yang dikandungnya. Itu melacak fungsi dan kelas referensi tetapi tidak mengandung, sehingga linker dapat menyelesaikannya nanti ketika menggabungkan kode objek ke dalam executable atau library.
Contoh
Foo.h
-> mengandung deklarasi (antarmuka) untuk kelas Foo.
Foo.cpp
-> mengandung definisi (implementasi) untuk kelas Foo.
Main.cpp
-> berisi metode utama, titik masuk program. Kode ini membuat Instan Foo dan menggunakannya.
Keduanya Foo.cpp
dan Main.cpp
perlu dimasukkan Foo.h
. Foo.cpp
membutuhkannya karena mendefinisikan kode yang mendukung antarmuka kelas, sehingga perlu tahu apa antarmuka itu. Main.cpp
membutuhkannya karena ia menciptakan Foo dan menjalankan perilakunya, sehingga ia harus tahu apa perilakunya, ukuran Foo dalam memori dan bagaimana menemukan fungsinya, dll. tetapi ia belum membutuhkan implementasi yang sebenarnya.
Compiler akan menghasilkan Foo.o
dari Foo.cpp
yang berisi semua kode kelas Foo dalam bentuk yang dikompilasi. Ini juga menghasilkan Main.o
yang mencakup metode utama dan referensi yang tidak terselesaikan ke kelas Foo.
Sekarang hadir tautan, yang menggabungkan dua file objek Foo.o
dan Main.o
menjadi file yang dapat dieksekusi. Ia melihat referensi Foo yang belum terselesaikan di Main.o
tetapi melihat yang Foo.o
berisi simbol yang diperlukan, sehingga "menghubungkan titik-titik" untuk berbicara. Panggilan fungsi Main.o
sekarang terhubung ke lokasi aktual dari kode yang dikompilasi sehingga pada saat runtime, program dapat melompat ke lokasi yang benar.
Jika Anda memasukkan Foo.cpp
file ke Main.cpp
dalamnya, akan ada dua definisi kelas Foo. Tautan akan melihat ini dan berkata, "Saya tidak tahu yang mana yang harus dipilih, jadi ini adalah kesalahan." Langkah kompilasi akan berhasil, tetapi menghubungkan tidak akan berhasil. (Kecuali Anda tidak mengkompilasi Foo.cpp
tetapi mengapa ia berada di .cpp
file yang terpisah ?)
Akhirnya, gagasan tentang jenis file yang berbeda tidak relevan dengan kompiler C / C ++. Ini mengkompilasi "file teks" yang diharapkan mengandung kode yang valid untuk bahasa yang diinginkan. Kadang-kadang mungkin bisa memberi tahu bahasa berdasarkan ekstensi file. Sebagai contoh, kompilasi .c
file tanpa opsi kompiler dan ia akan menganggap C, sementara ekstensi .cc
atau .cpp
akan memberitahu itu untuk menganggap C ++. Namun, saya dapat dengan mudah memberitahu kompiler untuk mengkompilasi .h
atau bahkan .docx
file sebagai C ++, dan itu akan memancarkan .o
file object ( ) jika mengandung kode C ++ yang valid dalam format teks biasa. Ekstensi ini lebih untuk kepentingan programmer. Jika saya melihat Foo.h
dan Foo.cpp
, saya langsung berasumsi bahwa yang pertama berisi deklarasi kelas dan yang kedua berisi definisi.