Dalam skenario apa lebih baik menggunakan struct
vs a class
di C ++?
Dalam skenario apa lebih baik menggunakan struct
vs a class
di C ++?
Jawaban:
Perbedaan antara a class
dan a struct
dalam C ++ adalah bahwa struct memiliki public
anggota dan pangkalan default dan kelas memiliki private
anggota dan pangkalan default . Baik kelas dan struct dapat memiliki campuran public
, protected
dan private
anggota, dapat menggunakan warisan dan dapat memiliki fungsi anggota.
Saya akan merekomendasikan menggunakan struct sebagai struktur data lama-polos tanpa fitur seperti kelas, dan menggunakan kelas sebagai struktur data agregat dengan private
data dan fungsi anggota.
Seperti yang dicatat semua orang, hanya ada dua perbedaan bahasa yang sebenarnya:
struct
default untuk akses publik dan class
default untuk akses pribadi.struct
bawaan ke public
warisan dan class
bawaan ke private
warisan. (Ironisnya, seperti halnya banyak hal dalam C ++, standarnya adalah mundur: public
pewarisan adalah pilihan yang lebih umum, tetapi orang jarang menyatakan struct
hanya untuk menghemat mengetik " public
" kata kunci.Tetapi perbedaan nyata dalam praktik adalah antara a class
/ struct
yang menyatakan konstruktor / destruktor dan yang tidak. Ada jaminan tertentu untuk tipe POD "data lama", yang tidak lagi berlaku setelah Anda mengambil alih konstruksi kelas. Agar perbedaan ini jelas, banyak orang yang sengaja hanya menggunakan struct
s untuk tipe POD, dan, jika mereka akan menambahkan metode apa pun, gunakan class
es. Perbedaan antara dua fragmen di bawah ini tidak ada artinya:
class X
{
public:
// ...
};
struct X
{
// ...
};
(Kebetulan, inilah utas dengan beberapa penjelasan yang bagus tentang apa sebenarnya arti "tipe POD": Apa tipe POD dalam C ++? )
struct
atau class
tidak memiliki kaitan apakah objek Anda adalah POD atau apakah Anda harus mendefinisikan copy constructor / destructor. Fungsi anggota juga tidak ada hubungannya dengan sesuatu yang menjadi POD. Ketika saya membaca kembali apa yang Anda tulis, saya melihat Anda tidak menyarankan sebaliknya, tetapi kata-kata saat ini membingungkan
Ada banyak kesalahpahaman dalam jawaban yang ada.
Keduanya class
dan struct
mendeklarasikan kelas.
Ya, Anda mungkin harus mengatur ulang akses Anda memodifikasi kata kunci di dalam definisi kelas, tergantung pada kata kunci yang Anda gunakan untuk mendeklarasikan kelas.
Tapi, di luar sintaks, satu - satunya alasan untuk memilih satu dari yang lain adalah konvensi / gaya / preferensi.
Beberapa orang suka tetap menggunakan struct
kata kunci untuk kelas tanpa fungsi anggota, karena definisi yang dihasilkan "terlihat seperti" struktur sederhana dari C.
Demikian pula, beberapa orang suka menggunakan class
kata kunci untuk kelas dengan fungsi dan private
data anggota, karena ia mengatakan "kelas" di atasnya dan karenanya terlihat seperti contoh dari buku favorit mereka tentang pemrograman berorientasi objek.
Kenyataannya adalah bahwa ini sepenuhnya terserah Anda dan tim Anda, dan itu tidak akan membuat perbedaan apa pun bagi program Anda.
Dua kelas berikut ini benar-benar setara dalam segala hal kecuali namanya:
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
Anda bahkan dapat mengganti kata kunci saat mendeklarasikan ulang:
class Foo;
struct Bar;
(walaupun ini memecah Visual Studio membangun karena ketidaksesuaian, sehingga kompiler akan memancarkan peringatan ketika Anda melakukan ini.)
dan ekspresi berikut keduanya dievaluasi menjadi true:
std::is_class<Foo>::value
std::is_class<Bar>::value
Namun, harap perhatikan bahwa Anda tidak dapat mengganti kata kunci saat mendefinisikan ulang ; ini hanya karena (per aturan satu definisi) duplikat definisi kelas di seluruh unit terjemahan harus "terdiri dari urutan token yang sama" . Ini berarti Anda bahkan tidak dapat bertukar const int member;
dengan int const member;
, dan tidak ada hubungannya dengan semantik class
atau struct
.
class foo { public: ... };
dan yang lain dapat memiliki struct foo { ... };
yang harus berlaku sesuai dengan klaim "benar-benar setara". Muncul alasan bahwa deklarasi tidak lengkap struct foo;
dan class foo;
dapat dipertukarkan. Ini tidak menentukan kelas tubuh, dan sehingga mereka tidak berbicara apa-apa dengan tata letak akses.
Foo
dan Bar
masih setara / jenis identik. Saya memang memastikan untuk mengatakan "ketika redeclaring " dan memberikan contoh. Kalau dipikir-pikir, saya akan mengklarifikasi ini dalam jawaban untuk memastikan saya tidak menyesatkan orang ke UB
Satu-satunya waktu saya menggunakan struct bukan kelas adalah ketika mendeklarasikan functor tepat sebelum menggunakannya dalam pemanggilan fungsi dan ingin meminimalkan sintaksis demi kejelasan. misalnya:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
Dari C ++ FAQ Lite :
Anggota dan kelas dasar dari suatu struct adalah publik secara default, sementara di kelas, mereka default ke pribadi. Catatan: Anda harus membuat kelas basis Anda secara eksplisit publik, pribadi, atau dilindungi, daripada mengandalkan default.
struct dan kelas dinyatakan setara secara fungsional.
OK, cukup bicara techno bersih yang melengking itu. Secara emosional, sebagian besar pengembang membuat perbedaan yang kuat antara kelas dan struct. Sebuah struct hanya terasa seperti tumpukan bit terbuka dengan sangat sedikit dalam cara enkapsulasi atau fungsionalitas. Kelas terasa seperti anggota masyarakat yang hidup dan bertanggung jawab dengan layanan cerdas, penghalang enkapsulasi yang kuat, dan antarmuka yang terdefinisi dengan baik. Karena itu konotasi yang sudah dimiliki kebanyakan orang, Anda mungkin harus menggunakan kata kunci struct jika Anda memiliki kelas yang memiliki sangat sedikit metode dan memiliki data publik (hal-hal seperti itu ada dalam sistem yang dirancang dengan baik!), Tetapi jika tidak, Anda mungkin harus menggunakan kelas tersebut kata kunci.
Satu tempat di mana struct telah membantu saya adalah ketika saya memiliki sistem yang menerima pesan format tetap (lebih dari katakan, port serial) dari sistem lain. Anda bisa memasukkan aliran byte ke dalam struktur yang mendefinisikan bidang Anda, dan kemudian dengan mudah mengakses bidang.
typedef struct
{
int messageId;
int messageCounter;
int messageData;
} tMessageType;
void processMessage(unsigned char *rawMessage)
{
tMessageType *messageFields = (tMessageType *)rawMessage;
printf("MessageId is %d\n", messageFields->messageId);
}
Jelas, ini adalah hal yang sama yang akan Anda lakukan di C, tetapi saya menemukan bahwa overhead harus men-decode pesan ke dalam kelas biasanya tidak sepadan.
operator >>
pada kelas alih-alih menulis processMessage
fungsi, yang akan membuat C ++ Anda lebih mirip C ++ yang tepat dan kurang seperti C.
__packed__
struct dan memiliki implementasi ifdef endian-aware (Anda perlu membalik urutan pada mesin di mana endianess berlawanan dengan apa yang sumber data eksternal menyediakan). Ini tidak cantik, tapi saya sudah terbiasa mengemas / membongkar register untuk periferal jarak jauh pada platform tertanam dengan cara yang portabel.
char
tipe, yang dikecualikan dari alias. Namun, masih ada masalah, meskipun yang berbeda: Casting char*
ke tipe yang berbeda, jika tidak benar-benar ada objek dari tipe terakhir yang sudah diinisialisasi di alamat itu, adalah UB karena melanggar aturan seumur hidup. Afaik, bahkan jika jenis tujuan sepele dibangun, hanya memiliki memori yang dialokasikan tidak cukup untuk C ++ untuk secara resmi memungkinkan memperlakukan memori itu sebagai jenis itu.
Anda dapat menggunakan "struct" di C ++ jika Anda menulis pustaka yang internalnya adalah C ++ tetapi API dapat dipanggil dengan kode C atau C ++. Anda cukup membuat satu tajuk yang berisi fungsi struct dan API global yang Anda paparkan ke kode C dan C ++ karena ini:
// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif
// Put your C struct's here
struct foo
{
...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;
// Put your C API functions here
void bar(foo *fun);
#ifdef __cpp
}
#endif
Kemudian Anda dapat menulis bilah fungsi () dalam file C ++ menggunakan kode C ++ dan membuatnya bisa dipanggil dari C dan kedua dunia dapat berbagi data melalui struct yang dinyatakan. Ada peringatan lain tentu saja ketika mencampur C dan C ++ tetapi ini adalah contoh yang disederhanakan.
Seperti yang dikatakan setiap orang, satu-satunya perbedaan nyata adalah akses default. Tapi saya terutama menggunakan struct ketika saya tidak ingin segala macam enkapsulasi dengan kelas data sederhana, bahkan jika saya menerapkan beberapa metode pembantu. Misalnya, ketika saya membutuhkan sesuatu seperti ini:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
Untuk menjawab pertanyaan saya sendiri (tanpa malu-malu), Seperti telah disebutkan, hak akses adalah satu-satunya perbedaan di antara mereka di C ++.
Saya cenderung menggunakan struct untuk penyimpanan data saja. Saya akan mengizinkannya untuk mendapatkan beberapa fungsi pembantu jika membuatnya bekerja dengan data lebih mudah. Namun begitu data membutuhkan kontrol aliran (yaitu getter / setter yang mempertahankan atau melindungi keadaan internal) atau mulai mengakuisisi setiap fungsi utama (pada dasarnya lebih seperti objek), itu akan 'ditingkatkan' ke kelas untuk mengomunikasikan maksud yang lebih baik.
Structs ( PODs , lebih umum) berguna ketika Anda menyediakan antarmuka yang kompatibel dengan C dengan implementasi C ++, karena mereka portabel melintasi batas-batas bahasa dan format tautan.
Jika itu bukan masalah bagi Anda, maka saya kira penggunaan "struct" bukan "kelas" adalah komunikator yang baik (seperti @ZeroSignal katakan di atas). Structs juga memiliki semantik penyalinan yang lebih mudah diprediksi, sehingga mereka berguna untuk data yang ingin Anda tulis ke media eksternal atau kirim melalui kabel.
Structs juga berguna untuk berbagai tugas pemrograman metaprogram, seperti templat ciri yang baru saja memaparkan sekelompok typedef dependen:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
... Tapi itu benar-benar hanya mengambil keuntungan dari tingkat perlindungan default struct menjadi publik ...
Untuk C ++, sebenarnya tidak ada banyak perbedaan antara struct dan kelas. Perbedaan fungsional utama adalah bahwa anggota struct adalah publik secara default, sementara mereka pribadi secara default di kelas. Kalau tidak, sejauh bahasanya, mereka setara.
Yang mengatakan, saya cenderung menggunakan struct di C ++ seperti yang saya lakukan di C #, mirip dengan apa yang dikatakan Brian. Struct adalah wadah data sederhana, sementara kelas digunakan untuk objek yang perlu bertindak pada data selain hanya berpegang pada itu.
Mereka adalah hal yang hampir sama. Berkat keajaiban C ++, sebuah struct dapat menyimpan fungsi, menggunakan pewarisan, dibuat menggunakan "baru" dan seterusnya seperti kelas
Satu-satunya perbedaan fungsional adalah bahwa kelas dimulai dengan hak akses pribadi, sedangkan struct dimulai dengan publik. Ini adalah menjaga kompatibilitas mundur dengan C.
Dalam praktiknya, saya selalu menggunakan struct sebagai pemegang data dan kelas sebagai objek.
Seperti yang ditunjukkan orang lain
Ada rekomendasi yang jelas tentang kapan harus menggunakan yang dari Stroustrup / Sutter:
Namun, perlu diingat bahwa tidak bijaksana untuk maju menyatakan sth. sebagai kelas ( class X;
) dan mendefinisikannya sebagai struct ( struct X { ... }
). Ini dapat bekerja pada beberapa penghubung (misalnya, g ++) dan mungkin gagal pada yang lain (misalnya, MSVC), sehingga Anda akan menemukan diri Anda dalam neraka pengembang.
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
tidak hanya mengkompilasi dan berjalan dengan MSVC 2017, bahkan menghasilkan peringatan yang jelas yang Foo
dinyatakan sebagai struct
tetapi didefinisikan sebagai class
. Tetapi saya juga ingat dengan jelas bahwa tim kami menghabiskan setengah hari untuk menemukan bug bodoh itu. Saya tidak yakin versi MSVC apa yang kami gunakan saat itu.
class
atau struct
pada deklarasi maju, dan keduanya secara bebas dipertukarkan sesuai standar (meskipun diketahui bahwa VS memperingatkan; Saya selalu berasumsi bahwa itu hanya untuk menghindari kesalahan programmer yang jelas). Sesuatu tidak berbau di sini. Apakah Anda yakin itu bukan bug pelanggaran ODR?
struct
-forwards ke class
-forwards, masalahnya hilang. Sampai hari ini, saya merasa aneh juga. Saya akan senang jika Anda bisa menjelaskannya.
Anggota kelas bersifat pribadi secara default.
class test_one {
int main_one();
};
Setara dengan
class test_one {
private:
int main_one();
};
Jadi, jika Anda mencoba
int two = one.main_one();
Kami akan mendapatkan kesalahan: main_one is private
karena tidak dapat diakses. Kita dapat menyelesaikannya dengan menginisialisasi dengan menentukan publik yaitu
class test_one {
public:
int main_one();
};
Sebuah struct adalah kelas di mana anggota bersifat publik secara default.
struct test_one {
int main_one;
};
Artinya main_one
adalah pribadi
class test_one {
public:
int main_one;
};
Saya menggunakan struct untuk struktur data di mana anggota dapat mengambil nilai apa pun, lebih mudah seperti itu.
Keuntungan struct
lebih class
adalah menyimpan satu baris kode, jika mengikuti "anggota publik pertama, lalu pribadi". Dalam terang ini, saya menemukan kata kunci class
tidak berguna.
Berikut adalah alasan lain untuk menggunakan saja struct
dan tidak pernah class
. Beberapa pedoman gaya kode untuk C ++ menyarankan menggunakan huruf kecil untuk makro fungsi, alasannya adalah bahwa ketika makro dikonversi ke fungsi inline, namanya tidak perlu diubah. Sama disini. Anda memiliki struct C-style yang bagus dan suatu hari, Anda tahu Anda perlu menambahkan konstruktor, atau beberapa metode kenyamanan. Apakah Anda mengubahnya menjadi class
? Dimana mana?
Membedakan antara struct
s dan class
es adalah terlalu banyak kesulitan, masuk ke cara melakukan apa yang seharusnya kita lakukan - pemrograman. Seperti banyak masalah C ++, masalah ini muncul karena keinginan kuat untuk kompatibilitas.
class
? Apakah Anda berpikir bahwa kelas yang ditentukan dengan struct
kata kunci tidak dapat memiliki fungsi anggota atau konstruktor?
joe()
harus ditentukan dengan class
kata kunci? Setiap kelas dengan minimal 4 int
anggota harus didefinisikan dengan struct
kata kunci?
struct
, agregat dengan metode didefinisikan dengan class
". Terlalu banyak kerumitan.
mereka adalah hal yang sama dengan standar yang berbeda (pribadi secara default untuk class
, dan publik secara default untuk struct
), jadi secara teori mereka benar-benar dapat dipertukarkan.
jadi, jika saya hanya ingin mengemas beberapa info untuk bergerak, saya menggunakan struct, bahkan jika saya meletakkan beberapa metode di sana (tetapi tidak banyak). Jika sebagian besar hal-hal yang buram, di mana penggunaan utama akan melalui metode, dan tidak langsung ke anggota data, saya menggunakan kelas penuh.
Structs secara default memiliki akses publik dan kelas-kelas secara default memiliki akses pribadi.
Secara pribadi saya menggunakan struct untuk Objek Transfer Data atau sebagai Objek Nilai. Ketika digunakan seperti itu saya menyatakan semua anggota sebagai const untuk mencegah modifikasi oleh kode lain.
Keduanya struct
dan class
sama di bawah tenda meskipun dengan standar berbeda untuk visibilitas, struct
default adalah publik dan class
default adalah pribadi. Anda dapat mengubah salah satu menjadi yang lain dengan penggunaan private
danpublic
. Keduanya memungkinkan pewarisan, metode, konstruktor, destruktor, dan semua barang lainnya dari bahasa yang berorientasi objek.
Namun satu perbedaan besar antara keduanya adalah bahwa struct
sebagai kata kunci didukung dalam C sedangkan class
tidak. Ini berarti bahwa seseorang dapat menggunakan struct
dalam include file yang dapat #include
menjadi baik C ++ atau C asalkan struct
adalah C gaya polos struct
dan segala sesuatu yang lain di include file kompatibel dengan C, yaitu tidak ada C ++ kata kunci tertentu seperti private
, public
, tidak ada metode, tidak ada warisan, dll. dll.
Gaya AC struct
dapat digunakan dengan antarmuka lain yang mendukung penggunaan gaya C struct
untuk membawa data bolak-balik melalui antarmuka.
Gaya AC struct
adalah sejenis templat (bukan templat C ++ tetapi lebih merupakan pola atau stensil) yang menggambarkan tata letak area memori. Selama bertahun-tahun interface yang dapat digunakan dari C dan dengan C plug-in (inilah melihat Anda Java dan Python dan Visual Basic) telah menciptakan beberapa yang bekerja dengan gaya C struct
.
Secara teknis keduanya sama dalam C ++ - misalnya mungkin untuk struct memiliki operator kelebihan beban dll.
Namun:
Saya menggunakan struct ketika saya ingin menyampaikan informasi dari beberapa jenis secara bersamaan saya menggunakan kelas ketika saya berurusan dengan objek "fungsional".
Semoga ini bisa membantu.
#include <string>
#include <map>
using namespace std;
struct student
{
int age;
string name;
map<string, int> grades
};
class ClassRoom
{
typedef map<string, student> student_map;
public :
student getStudentByName(string name) const
{ student_map::const_iterator m_it = students.find(name); return m_it->second; }
private :
student_map students;
};
Misalnya, saya mengembalikan siswa struct di metode get ... () di sini - selamat menikmati.
Kapan Anda memilih untuk menggunakan struct dan kapan harus menggunakan kelas di C ++?
Saya gunakan struct
ketika saya mendefinisikan functors
dan POD
. Kalau tidak saya gunakan class
.
// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
bool operator()(int first, int second)
{ return first < second; }
};
class mycompare : public std::binary_function<int, int, bool>
{
public:
bool operator()(int first, int second)
{ return first < second; }
};
std::binary_function<>
tidak hanya usang, c ++ 17 bahkan menghapusnya.
Semua anggota kelas adalah pribadi secara default dan semua anggota struct adalah publik secara default. Kelas memiliki pangkalan pribadi default dan Struct memiliki pangkalan publik default. Struct dalam kasus C tidak dapat memiliki fungsi anggota di mana seperti dalam kasus C ++ kita dapat memiliki fungsi anggota yang ditambahkan ke struct. Selain perbedaan-perbedaan ini, saya tidak menemukan sesuatu yang mengejutkan tentang mereka.
Saya menggunakan struct hanya ketika saya perlu menyimpan beberapa data tanpa fungsi anggota yang terkait dengannya (untuk beroperasi pada data anggota) dan untuk mengakses variabel data secara langsung.
Misalnya: Membaca / Menulis data dari file dan aliran socket dll. Melewati argumen fungsi dalam struktur di mana argumen fungsi terlalu banyak dan sintaks fungsi terlihat terlalu panjang.
Secara teknis tidak ada perbedaan besar antara kelas dan struture kecuali aksesibilitas default. Terlebih lagi itu tergantung pada gaya pemrograman bagaimana Anda menggunakannya.
Saya berpikir bahwa Structs dimaksudkan sebagai Struktur Data (seperti array tipe data multi-data) dan kelas diintegrasikan untuk Pengemasan Kode (seperti koleksi subrutin & fungsi).
:(
Saya tidak pernah menggunakan "struct" di C ++.
Saya tidak pernah bisa membayangkan skenario di mana Anda akan menggunakan struct ketika Anda ingin anggota pribadi, kecuali Anda sengaja berusaha untuk membingungkan.
Tampaknya menggunakan struct lebih merupakan indikasi sintaksis tentang bagaimana data akan digunakan, tetapi saya lebih suka hanya membuat kelas dan mencoba membuatnya secara eksplisit atas nama kelas, atau melalui komentar.
Misalnya
class PublicInputData {
//data members
};
struct
sudah cukup eksplisit bahwa anggota kelas akan, secara default, publik?