Saya seorang pengembang JAVA yang mencoba mempelajari C ++, tetapi saya tidak benar-benar tahu apa praktik terbaik untuk deklarasi fungsi standar.
Di dalam kelas:
class Clazz
{
public:
void Fun1()
{
//do something
}
}
Atau di luar:
class Clazz
{
public:
void Fun1();
}
Clazz::Fun1(){
// Do something
}
Saya merasa bahwa yang kedua kurang bisa dibaca ...
.cpp
file terpisah .inline
.inline
hanya melonggarkan aturan satu definisi, yang diperlukan jika unit terjemahan lain menggunakanClazz
Jawaban:
C ++ berorientasi objek, dalam arti mendukung paradigma berorientasi objek untuk pengembangan perangkat lunak.
Namun, berbeda dari Java, C ++ tidak memaksa Anda untuk mengelompokkan definisi fungsi di kelas: cara standar C ++ untuk mendeklarasikan fungsi adalah dengan mendeklarasikan fungsi, tanpa kelas apa pun.
Jika sebaliknya Anda berbicara tentang deklarasi / definisi metode maka cara standar adalah dengan meletakkan hanya deklarasi dalam file include (biasanya dinamai
.h
atau.hpp
) dan definisi dalam file implementasi terpisah (biasanya dinamai.cpp
atau.cxx
). Saya setuju ini memang agak menjengkelkan dan membutuhkan beberapa duplikasi tetapi begitulah cara bahasanya dirancang.Untuk eksperimen cepat dan proyek file tunggal, semuanya akan berhasil ... tetapi untuk proyek yang lebih besar, pemisahan ini secara praktis diperlukan.
Catatan: Meskipun Anda tahu Java, C ++ adalah bahasa yang sama sekali berbeda ... dan ini adalah bahasa yang tidak bisa dipelajari dengan bereksperimen. Alasannya adalah karena ini adalah bahasa yang agak rumit dengan banyak asimetri dan pilihan yang tampaknya tidak logis, dan yang terpenting, ketika Anda membuat kesalahan, tidak ada "malaikat kesalahan runtime" untuk menyelamatkan Anda seperti di Java ... tetapi ada " daemon perilaku tidak terdefinisi ".
Satu-satunya cara yang masuk akal untuk mempelajari C ++ adalah dengan membaca ... tidak peduli seberapa pintar Anda tidak mungkin Anda dapat menebak apa yang diputuskan panitia (sebenarnya menjadi pintar terkadang malah menjadi masalah karena jawaban yang benar tidak logis dan konsekuensi dari sejarah warisan.)
Pilih saja satu atau dua buku yang bagus dan bacalah dari sampul ke sampul.
sumber
Yang pertama mendefinisikan fungsi anggota Anda sebagai fungsi sebaris , sedangkan yang kedua tidak. Definisi fungsi dalam hal ini berada di header itu sendiri.
Implementasi kedua akan menempatkan definisi fungsi di file cpp.
Keduanya berbeda secara semantik dan ini bukan hanya soal gaya.
sumber
Definisi fungsi lebih baik di luar kelas. Dengan begitu, kode Anda dapat tetap aman jika diperlukan. File header seharusnya hanya memberikan deklarasi.
Misalkan seseorang ingin menggunakan kode Anda, Anda dapat memberinya file .h dan file .obj (diperoleh setelah kompilasi) dari kelas Anda. Dia tidak membutuhkan file .cpp untuk menggunakan kode Anda.
Dengan begitu, implementasi Anda tidak terlihat oleh orang lain.
sumber
Metode "Di dalam kelas" (I) melakukan hal yang sama seperti metode "di luar kelas" (O).
Namun, (I) dapat digunakan ketika kelas hanya digunakan dalam satu file (di dalam file .cpp). (O) digunakan saat berada di file header. file cpp selalu dikompilasi. File header dikompilasi saat Anda menggunakan #include "header.h".
Jika Anda menggunakan (I) di file header, fungsi (Fun1) akan dideklarasikan setiap kali Anda menyertakan #include "header.h". Ini dapat menyebabkan mendeklarasikan fungsi yang sama beberapa kali. Ini lebih sulit untuk dikompilasi, dan bahkan dapat menyebabkan kesalahan.
Contoh penggunaan yang benar:
File1: "Clazz.h"
//This file sets up the class with a prototype body. class Clazz { public: void Fun1();//This is a Fun1 Prototype. };
File2: "Clazz.cpp"
#include "Clazz.h" //this file gives Fun1() (prototyped in the header) a body once. void Clazz::Fun1() { //Do stuff... }
File3: "UseClazz.cpp"
#include "Clazz.h" //This file uses Fun1() but does not care where Fun1 was given a body. class MyClazz; MyClazz.Fun1();//This does Fun1, as prototyped in the header.
File4: "JugaUseClazz.cpp"
#include "Clazz.h" //This file uses Fun1() but does not care where Fun1 was given a body. class MyClazz2; MyClazz2.Fun1();//This does Fun1, as prototyped in the header.
File5: "DoNotUseClazzHeader.cpp"
//here we do not include Clazz.h. So this is another scope. class Clazz { public: void Fun1() { //Do something else... } }; class MyClazz; //this is a totally different thing. MyClazz.Fun1(); //this does something else.
sumber
Clazz MyClazz
danClazz MyClazz2
?Fungsi anggota dapat didefinisikan dalam definisi kelas atau secara terpisah menggunakan operator resolusi lingkup, ::. Mendefinisikan fungsi anggota dalam definisi kelas mendeklarasikan fungsi sebaris, meskipun Anda tidak menggunakan penentu sebaris. Jadi, Anda dapat menentukan fungsi Volume () seperti di bawah ini:
class Box { public: double length; double breadth; double height; double getVolume(void) { return length * breadth * height; } };
Jika Anda suka, Anda dapat mendefinisikan fungsi yang sama di luar kelas menggunakan operator resolusi lingkup, :: sebagai berikut
double Box::getVolume(void) { return length * breadth * height; }
Di sini, satu-satunya poin penting adalah Anda harus menggunakan nama kelas sebelum :: operator. Fungsi anggota akan dipanggil menggunakan operator titik (.) Pada objek yang akan memanipulasi data yang terkait dengan objek itu hanya sebagai berikut:
(dari: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm ), kedua cara tersebut legal.
Saya bukan ahli, tapi menurut saya, jika Anda hanya memasukkan satu definisi kelas dalam satu file, maka itu tidak terlalu penting.
tetapi jika Anda menerapkan sesuatu seperti kelas dalam, atau Anda memiliki definisi kelas ganda, definisi kelas kedua akan sulit dibaca dan dipertahankan.
sumber
Yang pertama harus diletakkan di file header (tempat deklarasi kelas berada). Yang kedua bisa di mana saja, baik header atau, biasanya, file sumber. Dalam praktiknya, Anda bisa meletakkan fungsi kecil di deklarasi kelas (yang mendeklarasikannya secara implisit, meskipun compiler-lah yang pada akhirnya memutuskan apakah mereka akan sebaris atau tidak). Namun, sebagian besar fungsi memiliki deklarasi di header dan implementasinya dalam file cpp, seperti dalam contoh kedua Anda. Dan tidak, saya tidak melihat alasan mengapa ini menjadi kurang terbaca. Belum lagi Anda benar-benar dapat membagi implementasi untuk suatu tipe di beberapa file cpp.
sumber
Fungsi yang didefinisikan di dalam kelas secara default diperlakukan sebagai fungsi sebaris. Alasan sederhana mengapa Anda harus mendefinisikan fungsi Anda di luar:
Konstruktor kelas memeriksa fungsi virtual dan menginisialisasi penunjuk virtual untuk menunjuk ke VTABLE yang tepat atau tabel metode virtual , memanggil konstruktor kelas dasar, dan menginisialisasi variabel kelas saat ini, sehingga sebenarnya melakukan beberapa pekerjaan.
Fungsi inline digunakan ketika fungsi tidak begitu rumit dan menghindari overhead pemanggilan fungsi. (Overhead mencakup lompatan dan cabang pada tingkat perangkat keras.) Dan seperti dijelaskan di atas, konstruktor tidak sesederhana untuk dianggap sebaris.
sumber
Fungsi sebaris (fungsi saat Anda mendeklarasikannya di kelas) setiap kali memanggilnya, fungsi tersebut ditempelkan dalam kode memeory utama Anda. Sedangkan saat Anda mendeklarasikan fungsi di luar kelas, saat Anda memanggil fuction itu berasal dari memori yang sama. Itulah mengapa jauh lebih baik.
sumber