Apa yang harus saya lakukan jika saya benci file header C ++?

25

Saya selalu bingung tentang file header. Mereka sangat aneh: Anda memasukkan file .h yang tidak termasuk .cpp tetapi .cpp entah bagaimana dikompilasi juga.

Baru-baru ini saya bergabung dengan proyek tim, dan tentu saja, keduanya .h dan .cpp digunakan.
Saya mengerti bahwa ini sangat penting, tapi saya tidak bisa hidup dengan copy-paste setiap deklarasi fungsi di masing-masing beberapa kelas yang kita miliki.

Bagaimana cara menangani konvensi 2-file secara efisien?
Apakah ada alat untuk membantu dengan itu, atau secara otomatis mengubah satu file yang terlihat seperti contoh di bawah ini menjadi .h dan .cpp? (khusus untuk MS VC ++ 2010)

class A
{
...
    Type f(Type a,Type b)
    {
        //implementation here, not in another file!
    }
...
};

Type f(Type a)
{
     //implementation here
}
...
Oleh Prypin
sumber
8
Pertanyaan ini bisa terdiri dari beberapa cara .. "Mengapa kita perlu header ketika menggunakan c ++" atau, "Apakah Anda pikir bahasa modern yang dimaksudkan untuk dikompilasi harus menggunakan header?" Seperti itu, ia memiliki 'Apa yang harus saya lakukan "dan" benci "dalam judul, yang memicu sejumlah besar bendera.
Tim Post
4
Pertanyaan Anda membuatnya tampak seperti Anda tidak mengerti C ++, atau bagaimana sistem apa pun yang Anda gunakan mengkompilasinya. Belajarlah untuk menggunakannya dengan benar, dan kemudian ajukan lebih banyak pertanyaan subjektif.
David Thornley
31
Kalimat pertama Anda menunjukkan bahwa Anda tidak "memahami segala sesuatu tentang tajuk". Termasuk file .h tidak menyebabkan file .cpp yang sesuai menjadi "entah bagaimana dikompilasi juga". Anda mengkompilasi file .cpp secara independen dalam hak mereka sendiri. Jika Anda belum mengompilasi .cpp yang sesuai, maka dimasukkannya header tanpa file objek yang sesuai akan menyebabkan tautan gagal.
Paul Butcher
5
Melakukan apa? Temukan bahasa lain jika itu mengganggu Anda.
Paul Nathan
5
Tentang "tidak dapat hidup dengan copy-paste": Setiap kali seseorang memperbarui suatu fungsi, ia harus memperbarui semua tempat di mana ia dipanggil. Karena penelepon jauh lebih sulit ditemukan daripada pernyataan dalam file header, memperbarui header hanyalah detail kecil.
Sjoerd

Jawaban:

15

Menulis Lebih Ramah Refactoring C ++

Di C ++ Anda tidak harus menggunakan header sama sekali. Anda dapat mendefinisikan seluruh objek dalam satu file seperti yang Anda lakukan dengan C # atau Java. Pengembang C umumnya hanya akan menyimpan panggilan eksternal dalam file header. Semua panggilan internal akan ditentukan dalam file .c. Dengan cara yang sama, Anda dapat memesan file C ++ .h untuk kelas / antarmuka (kelas abstrak virtual murni) / etc. yang dimaksudkan untuk dibagikan di luar DLL. Untuk kelas / struct / antarmuka internal, dll. Anda cukup menyertakan file .cpp yang Anda butuhkan:

#include<myclass.cpp>

Ini sepertinya bukan pendekatan yang paling populer, tetapi ini legal C ++. Pasti akan menjadi kemungkinan untuk semua kode internal Anda. Ini memungkinkan kode internal dan sekumpulan kelas untuk berubah lebih banyak secara radikal sambil menyediakan antarmuka yang lebih stabil untuk kode di luar perpustakaan Anda / yang dapat dieksekusi untuk berinteraksi.

Memiliki seluruh kelas Anda di dalam satu file akan membuatnya lebih mudah untuk melakukan apa yang Anda inginkan. Itu tidak akan menyelesaikan masalah penggantian nama metode dan harus mencari ke setiap tempat metode itu dipanggil, tetapi itu akan memastikan Anda memiliki pesan kesalahan yang lebih dapat dipahami. Tidak ada yang lebih buruk daripada memiliki header Anda mendeklarasikan metode satu arah, tetapi Anda menerapkannya secara berbeda. Kode lain yang memanggil file header akan dikompilasi dengan benar dan Anda akan mendapatkan pengecualian tautan, sementara file implementasi akan menjadi salah satu yang mengeluh bahwa metode itu tidak didefinisikan. Ketika Anda mendefinisikan setiap metode di tempat (dalam deklarasi kelas yang sebenarnya), Anda akan mendapatkan pesan kesalahan yang sama tidak peduli file apa yang menyertakannya.

Anda mungkin juga ingin melihat pertanyaan ini: Alat refactoring yang bagus untuk C ++

Bagaimana C / C ++ Menyelesaikan File Header / Implementasi

Pada level C dasar (dan C ++ dibangun di atas fondasi itu), file header menyatakan janji fungsi / struct / variabel yang cukup untuk memungkinkan kompiler membuat file objek. Demikian pula file header C ++ menyatakan janji fungsi, struct, kelas, dll. Ini adalah definisi yang digunakan kompilator untuk memesan ruang di stack, dll.

File .c atau .cpp memiliki implementasinya. Ketika kompiler mengonversi setiap file implementasi ke file objek, ada kait ke konsep yang tidak diterapkan (apa yang dinyatakan dalam header). Tautan mengikat kait ke implementasi di file objek lain dan membuat biner yang lebih besar yang mencakup semua kode (shared library atau executable).

VS Spesifik

Untuk bekerja dengan orang-orang di Visual Studio, ada beberapa penyihir yang membantu membuat segalanya lebih mudah. Wizard kelas baru akan membuat pasangan header dan file implementasi yang cocok. Bahkan ada fitur browser kelas yang akan memungkinkan Anda mendeklarasikan metode baru. Ini akan menyuntikkan definisi di header dan rintisan implementasi dalam file .cpp. Visual Studio telah memiliki fitur-fitur tersebut selama lebih dari satu dekade (selama saya telah menggunakannya).

Berin Loritsch
sumber
Masalahnya adalah, aku sangat memodifikasi kelas sepanjang waktu, tidak hanya menambahkan fungsi baru, dll
Oleh Prypin
5
@BlaXpirit: Jadi, mengapa Anda banyak memodifikasi kelas setiap saat? Salah satu ide di balik desain OO adalah memiliki banyak blok bangunan yang cukup stabil. Jika saya banyak memodifikasi kelas, saya ingin bahasa yang lebih dinamis, seperti Common Lisp atau Python.
David Thornley
2
Itu yang saya lakukan. Saya meningkatkan / memodifikasi "blok bangunan" dan menambahkan yang baru
Oleh Prypin
C ++ tidak pernah ramah untuk refactoring. Konsep refactoring tidak mendapatkan momentum sampai ada alat yang membuatnya sangat mudah dilakukan di Java IDEs. CATATAN: fitur-fitur itu ada untuk pengembang Smalltalk, dan bahasa lainnya, tetapi itu tidak menjadi arus utama sampai tersedia untuk banyak orang. Sejauh ini saya belum melihat seseorang yang secara cerdas mengimplementasikannya untuk C ++. Mungkin Resharper dari JetBrains? Saya tahu kode C # dan VB, tapi saya tidak yakin apakah itu akan memberi Anda C ++ refactoring.
Berin Loritsch
@Berin: Saya mencari alat refactoring C ++ setahun atau dua tahun lalu, dan menemukan dua hal. Mereka cukup mahal pada saat itu, dan saya tidak melihat versi percobaan, jadi saya tidak tahu apa yang mereka lakukan. Selain itu, satu bekerja dengan emacs saja, yang akan membatasi efektivitasnya di toko Visual Studio.
David Thornley
13

Menjadi pengembang Java.

Jika Anda benar-benar harus terus mengembangkan C ++, Anda dapat mencoba menggunakan IDE. Seringkali mereka menawarkan beberapa mekanisme di mana Anda dapat menambahkan metode ke kelas, dan itu secara otomatis menempatkan deklarasi dalam file .h dan definisi dalam file .cpp.

Paul Butcher
sumber
2
kthx, saya agak tahu Java, tetapi Anda tidak dapat membuat Win32 DLL tingkat rendah dengan itu, bukan?
Oleh Prypin
41
Saya tidak tahu mengapa, tapi 'Menjadi pengembang Java' entah bagaimana terdengar seperti penghinaan: D.
Oliver Weiler
2
Jika Anda ingin melakukan level rendah, lupakan segala sesuatu tentang 'bahasa mudah'. Tingkat rendah menyebabkan keringat dan air mata.
Batibix
5
Bukan jawaban yang sangat membantu.
ChrisF
1
@ OliverWeiler Saya tidak menganggap "menjadi pengembang Java" sebagai penghinaan. Saya memprogram baik dalam C ++ dan Java, tetapi preferensi saya sejauh ini adalah Java karena jauh lebih mudah untuk duduk dan mengeluarkan kode yang berfungsi (dan lebih portabel). Jika Anda karena suatu alasan membenci keberadaan file header, mencoba Java mungkin merupakan pilihan yang tepat (meskipun aneh Anda akan membenci file header; Saya akan mempertimbangkan perubahan dalam IDE).
Trixie Wolf
7

Anda bisa tertarik pada makeheaders program dari Hwaci (orang-orang yang SQLite dan Fosil).

Lihat juga bagaimana fosil dibangun untuk memiliki ide.

Benoit
sumber
5
Penanya masih perlu memahami hubungan antara .h dan .cpp dengan cukup baik.
Pekerjaan
2
Saya mengerti dasar-dasarnya. Jawabannya sepertinya hanya yang saya butuhkan.
Oleh Prypin
4

Ketika Anda menulis baris pertama dari sebuah kelas baru, biasanya itu karena Anda membutuhkannya di satu tempat hanya pada waktu itu. Di lain waktu, mungkin digunakan di lebih banyak tempat, tetapi pada awalnya biasanya tidak.

Banyak kelas saya mulai di bagian atas file .cpp saat ini. Ketika sudah cukup stabil untuk menggunakannya di banyak tempat, saya potong-tempel ke header. Meskipun seringkali kelasnya menghilang secepat itu muncul.

Sjoerd
sumber
-1

Sebagai saran untuk membantu menangani file header C ++, biasanya digunakan tanpa ekstensi file atau akhiran file, seperti yang dilakukan oleh pustaka "GCC".

Jika ini adalah kasus Anda, saya sarankan untuk menggunakan ekstensi file atau akhiran file " .hpp" (atau unleast " .hxx").

Anda mungkin harus mengonfigurasi kompiler, lingkungan pengembang, atau program Bangun.

umlcat
sumber
3
Apakah Anda berbicara tentang bagaimana ketika Anda memasukkan file seperti #include <iostream>? Itu bukan hanya untuk perpustakaan GCC. Bahkan, itu didefinisikan dalam standar C ++ 1997 , bagian 17.3.1.2. Saya akan menghindari penamaan file seperti itu. Anda bisa, tetapi alasan pustaka standar C ++ melakukan itu mungkin untuk menghindari konflik penamaan. Saya benar-benar merasa aneh ketika kompiler secara otomatis menambahkan '.h' ketika Anda memasukkan header, sepertinya cukup tidak standar bagi saya. Dan saya tidak pernah melihat header nama siapa pun tanpa akhiran kecuali untuk pustaka standar c ++.
vedosity
1
Juga, saya harus perhatikan, semua kompiler yang telah saya gunakan, kecuali untuk borland (yang sangat saya benci), jangan secara otomatis menambahkan '.h' atau '.hpp' atau '.hxx' ketika Anda mencoba untuk memasukkan file tanpa akhiran. Jangan berharap #include <someclass>dibaca seperti #include <someclass.hpp>pada semua kompiler. Kode Anda akan rusak.
vedosity