Mengapa objek dari kelas yang sama memiliki akses ke data pribadi satu sama lain?
class TrivialClass {
public:
TrivialClass(const std::string& data) :
mData(data) {};
const std::string& getData(const TrivialClass& rhs) const {
return rhs.mData;
};
private:
std::string mData;
};
int main() {
TrivialClass a("fish");
TrivialClass b("heads");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
Kode ini berfungsi. Sangat mungkin bagi objek a untuk mengakses data pribadi dari objek b dan mengembalikannya. Mengapa harus demikian? Menurut saya, data pribadi itu pribadi. (Saya mulai dengan mencoba memahami konstruktor salinan dalam idiom pimpl, tetapi kemudian saya menemukan bahwa saya bahkan tidak memahami situasi sederhana ini.)
c++
private-members
Keith
sumber
sumber
Jawaban:
Karena begitulah cara kerjanya di C ++. Di C ++ kontrol akses bekerja pada basis per kelas , bukan pada basis per objek.
Kontrol akses di C ++ diimplementasikan sebagai fitur waktu kompilasi statis. Saya pikir cukup jelas bahwa tidak mungkin untuk menerapkan kontrol akses per objek yang berarti pada waktu kompilasi. Hanya kontrol per kelas yang dapat diterapkan dengan cara itu.
Beberapa petunjuk tentang kontrol per objek terdapat dalam spesifikasi akses yang dilindungi , itulah sebabnya ia bahkan memiliki bab tersendiri dalam standar (11.5). Tapi tetap saja, fitur per objek yang dijelaskan di sana masih belum sempurna. Sekali lagi, kontrol akses di C ++ dimaksudkan untuk bekerja pada basis per kelas.
sumber
void X::f(X&x)
, penyusun dengan mudah mampu membedakanthis->a
danx.a
. Tidak (selalu) mungkin bagi kompilator untuk mengetahui hal itu*this
danx
sebenarnya adalah objek yang sama jikax.f(x)
dipanggil, tetapi saya bisa melihat desainer bahasa menemukan ini OK.this
dan&x
adalah sama. Untuk membuatnya lebih buruk ini sebenarnya berakhir menjadi masalah bahkan denganX::f(Y& y)
, karena objek konkret kita bisa menjadi tipeZ
yang mewarisi dariX
danY
. Singkatnya, ini benar-benar berantakan, tidak berkinerja baik, sulit untuk bekerja dengan MI.X::f(X& x)
, jika ada akses kex.a
, itu tidak akan dikompilasi. Tidak ada perubahan lain, tidak ada pemeriksaan yang perlu dimasukkan, sehingga kinerja program yang masih valid tidak terpengaruh. Dan itu tidak disarankan sebagai perubahan besar pada C ++ yang sudah ada, tetapi sebagai sesuatu yang desainer bisa lakukan saat memperkenalkanprivate
aslinya."Pribadi" sebenarnya bukan mekanisme kontrol akses dalam arti "Saya membuat foto saya di facebook menjadi pribadi sehingga Anda tidak dapat melihatnya."
Di C ++, "private" hanya mengatakan ini adalah bagian dari kelas yang Anda (pembuat kode kelas) mungkin ubah di versi mendatang, dll., Dan Anda tidak ingin pembuat kode lain menggunakan kelas Anda untuk mengandalkan keberadaan atau fungsionalitas mereka .
Jika Anda menginginkan kontrol akses yang benar, Anda harus menerapkan teknik keamanan data asli.
sumber
Ini adalah pertanyaan yang bagus dan saya telah menemukan pertanyaan ini baru-baru ini. Saya berdiskusi dengan rekan-rekan saya dan inilah ringkasan dari diskusi kami: Ini memang disengaja. Ini tidak berarti desain ini benar-benar masuk akal untuk semua kasus, tetapi harus ada beberapa pertimbangan mengapa privat per kelas dipilih. Kemungkinan alasan yang dapat kami pikirkan meliputi:
Pertama-tama, biaya kontrol akses per instance bisa sangat tinggi. Ini telah dibahas oleh orang lain di utas ini. Secara teori, ini dapat dilakukan melalui pemeriksaan penunjuk ini . Namun, ini tidak dapat dilakukan pada waktu kompilasi, dan hanya dapat dilakukan pada waktu proses. Jadi, Anda harus mengidentifikasi kontrol akses setiap anggota pada waktu proses, dan jika dilanggar mungkin hanya pengecualian yang akan dimunculkan. Biayanya tinggi.
Kedua, kontrol akses per kelas memiliki kasus penggunaannya sendiri, seperti copy constructor atau operator =. Akan sulit untuk menerapkannya jika kontrol akses per instance.
Selain itu, kontrol akses terutama dari perspektif pemrograman / bahasa, untuk bagaimana memodulisasi / mengontrol akses ke kode / anggota, bukan datanya.
sumber
Ini semacam keputusan desain bahasa yang sewenang-wenang. Di Ruby , misalnya,
private
benar-benar berarti pribadi, seperti dalam "hanya instance yang dapat mengakses anggota data pribadinya sendiri". Namun, ini agak membatasi.Seperti yang ditunjukkan dalam komentar, pembuat salinan dan operator penugasan adalah tempat umum di mana Anda mengakses anggota data pribadi instance lain secara langsung. Ada alasan yang kurang jelas mengapa.
Perhatikan kasus berikut ini. Anda menerapkan daftar tertaut OO. Daftar tertaut memiliki kelas node bersarang untuk mengelola pointer. Anda dapat mengimplementasikan kelas node ini sedemikian rupa sehingga ia mengelola penunjuk itu sendiri (daripada menjadikan penunjuknya publik dan dikelola oleh daftar). Dalam kasus seperti itu, Anda akan memiliki objek node yang ingin memodifikasi pointer objek node lain di tempat lain yang merupakan copy konstruktor dan operator penugasan.
sumber
Triknya adalah dengan mengingat bahwa datanya adalah
private
ke kelas , bukan ke instance kelas. Setiap metode dalam kelas Anda dapat mengakses data pribadi dari setiap instance kelas itu; tidak ada cara untuk menjaga kerahasiaan data dalam sebuah instance kecuali Anda melarang metode yang secara eksplisit mengakses anggota data pribadi dari instance lain.sumber
Selain semua jawaban di atas, pertimbangkan konstruktor salinan kustom, operator tugas, dan semua fungsi lain yang akan Anda tulis untuk kelas yang beroperasi pada instance lain . Anda akan membutuhkan fungsi pengakses untuk semua anggota data tersebut.
sumber
Data pribadi tetap bersifat pribadi sampai seseorang yang memiliki akses ke data tersebut mengungkapkannya kepada orang lain.
Konsep ini juga berlaku untuk situasi lain, seperti:
Bagaimana orang bisa menarik uang itu? :)
sumber