Inilah yang saya maksud:
class MyClass {
int arr1[100];
int arr2[100];
int len = 100;
void add(int* x1, int* x2, int size) {
for (int i = 0; i < size; i++) {
x1[i] += x2[i];
}
}
};
int main() {
MyClass myInstance;
// Fill the arrays...
myInstance.add(myInstance.arr1, myInstance.arr2, myInstance.len);
}
add
sudah dapat mengakses semua variabel yang dibutuhkan, karena ini adalah metode kelas, jadi apakah ini ide yang buruk? Adakah alasan mengapa saya harus atau tidak melakukan ini?
object-oriented
c++
class-design
methods
encapsulation
tukang kertas
sumber
sumber
add
yang beroperasi secara internal? Kenapa?add
metode yang mengambil argumen tetapi tidak ada sebagai bagian dari kelas. Hanya fungsi murni untuk menambahkan dua array bersamaan.Jawaban:
Mungkin ada beberapa hal dengan kelas yang akan saya lakukan secara berbeda, tetapi untuk menjawab pertanyaan langsung, jawaban saya adalah
ya, itu ide yang buruk
Alasan utama saya untuk ini adalah bahwa Anda tidak memiliki kendali atas apa yang diteruskan ke
add
fungsi. Tentu Anda berharap ini adalah salah satu array anggota, tetapi apa yang terjadi jika seseorang melewati dalam array yang berbeda yang memiliki ukuran lebih kecil dari 100, atau Anda memberikan panjang lebih dari 100?Apa yang terjadi adalah Anda telah menciptakan kemungkinan buffer overrun. Dan itu adalah hal buruk di sekitar.
Untuk menjawab beberapa pertanyaan (bagi saya) yang jelas:
Anda mencampur array gaya C dengan C ++. Saya bukan guru C ++, tetapi saya tahu bahwa C ++ memiliki cara penanganan array yang lebih baik (lebih aman)
Jika kelas sudah memiliki variabel anggota, mengapa Anda harus meneruskannya? Ini lebih merupakan pertanyaan arsitektur.
Orang lain yang memiliki lebih banyak pengalaman C ++ (saya berhenti menggunakannya 10 atau 15 tahun yang lalu) mungkin memiliki cara yang lebih fasih dalam menjelaskan masalah, dan mungkin akan menghasilkan lebih banyak masalah juga.
sumber
vector<int>
akan lebih cocok; panjang kemudian tidak akan berguna. Atauconst int len
, karena array panjang variabel bukan bagian dari standar C ++ (walaupun beberapa kompiler mendukungnya, karena ini adalah fitur opsional di C).std::array
yang tidak membusuk ketika mengirimkannya ke parameter, memiliki cara yang lebih mudah untuk mendapatkan ukurannya, dapat disalin dan memiliki akses dengan batas pemeriksaan opsional, sementara tidak memiliki overhead lebih dari Array gaya C.Memanggil metode kelas dengan beberapa variabel kelas belum tentu buruk. Tetapi melakukannya dari luar kelas adalah ide yang sangat buruk dan menyarankan cacat mendasar dalam desain OO Anda, yaitu tidak adanya enkapsulasi yang tepat :
len
adalah panjang dari array, dan menggunakannya secara konsisten. Ini bertentangan dengan prinsip ilmu yang paling sedikit . Ketergantungan seperti itu pada detail bagian dalam kelas sangat rawan kesalahan dan berisiko.len
ke yang lebih modernstd::vector<int>
), karena itu mengharuskan Anda untuk juga mengubah semua kode menggunakan kelas Anda.MyClass
objek Anda dengan merusak beberapa variabel publik tanpa mematuhi aturan (disebut invarian kelas )Anda harus memperbaiki kode Anda, dan:
private
atauprotected
, kecuali ada alasan bagus untuk tidak melakukannya.object.action(additional parameters for the action)
.sumber
Ketika maksud dari desain ini adalah bahwa Anda ingin dapat menggunakan kembali metode ini untuk data yang tidak berasal dari instance kelas ini, maka Anda mungkin ingin mendeklarasikannya sebagai
static
metode .Metode statis bukan milik instance partikel dari kelas. Ini lebih merupakan metode kelas itu sendiri. Karena metode statis tidak dijalankan dalam konteks instance kelas apa pun, mereka hanya dapat mengakses variabel anggota yang juga dinyatakan sebagai statis. Menimbang bahwa metode
add
Anda tidak merujuk ke variabel anggota mana pun yang dideklarasikanMyClass
, itu adalah kandidat yang baik untuk dinyatakan sebagai statis.Namun, masalah keamanan yang disebutkan oleh jawaban lain valid: Anda tidak memeriksa apakah kedua array setidaknya
len
panjang. Jika Anda ingin menulis C ++ yang modern dan kuat, maka Anda harus menghindari penggunaan array. Gunakan kelasstd::vector
sebagai gantinya bila memungkinkan. Berlawanan dengan array reguler, vektor tahu ukurannya sendiri. Jadi, Anda tidak perlu melacak ukurannya sendiri. Sebagian besar (tidak semua!) Metode mereka juga melakukan pengecekan terikat otomatis, yang menjamin bahwa Anda mendapatkan pengecualian ketika Anda membaca atau menulis melewati akhir. Akses array reguler tidak melakukan pengecekan terikat, yang menghasilkan segfault yang terbaik dan dapat menyebabkan kerentanan buffer overflow yang dapat dieksploitasi lebih buruk.sumber
Sebuah metode di kelas idealnya memanipulasi data yang dienkapsulasi di dalam kelas. Dalam contoh Anda, tidak ada alasan untuk metode add untuk memiliki parameter apa pun, cukup gunakan properti kelas.
sumber
Melewati (bagian dari) objek ke fungsi anggota tidak masalah. Saat menerapkan fungsi Anda, Anda harus selalu waspada terhadap kemungkinan alias , dan konsekuensinya.
Tentu saja, kontrak mungkin meninggalkan beberapa jenis aliasing tidak terdefinisi bahkan jika bahasa mendukungnya.
Contoh yang menonjol:
Penugasan-gerak-sendiri di sisi lain, meskipun seharusnya tidak meledak di wajah Anda, tidak perlu menjadi larangan.
v.push_back(v[2]);
.std::copy()
mengasumsikan tujuan tidak dimulai di dalam sumber.Tetapi contoh Anda memiliki masalah yang berbeda:
this
. Kerjanya seperti fungsi utilitas gratis yang hanya di tempat yang salah.Singkatnya: Ya, contoh ini buruk. Tetapi bukan karena fungsi anggota dilewatkan anggota-objek.
sumber
Secara khusus melakukan ini adalah ide yang buruk karena beberapa alasan bagus, tetapi saya tidak yakin semuanya merupakan bagian integral dari pertanyaan Anda:
vector<int>
akan membuat hidup Anda lebih mudah.sumber
Ini adalah pendekatan "C dengan kelas" klasik ke C ++. Pada kenyataannya, ini bukan apa yang akan ditulis oleh programmer C ++ berpengalaman. Pertama, menggunakan array C mentah cukup banyak dicegah secara universal, kecuali jika Anda menerapkan perpustakaan kontainer.
Sesuatu seperti ini akan lebih sesuai:
sumber