Anggota Pribadi dan Terlindungi: C ++

276

Bisakah seseorang mencerahkan saya tentang perbedaan antara privatedan protectedanggota di kelas?

Saya mengerti dari konvensi praktik terbaik bahwa variabel dan fungsi yang tidak disebut di luar kelas harus dibuat private- tetapi melihat proyek MFC saya , MFC tampaknya lebih disukai protected.

Apa bedanya dan mana yang harus saya gunakan?

Konrad
sumber

Jawaban:

374

Anggota pribadi hanya dapat diakses di dalam kelas yang mendefinisikan mereka.

Anggota yang dilindungi dapat diakses di kelas yang mendefinisikan mereka dan di kelas yang mewarisi dari kelas itu.

Sunting: Keduanya juga dapat diakses oleh teman-teman dari kelas mereka, dan dalam hal anggota yang dilindungi, oleh teman-teman dari kelas yang diturunkan.

Sunting 2: Gunakan apa pun yang masuk akal dalam konteks masalah Anda. Anda harus mencoba membuat anggota menjadi pribadi kapan saja Anda bisa untuk mengurangi kopling dan melindungi implementasi kelas dasar, tetapi jika itu tidak memungkinkan, gunakan anggota yang dilindungi. Periksa C ++ FAQ untuk pemahaman yang lebih baik tentang masalah ini. Pertanyaan tentang variabel yang dilindungi ini mungkin juga membantu.

Firas Assaad
sumber
12
Tautan ke C ++ FAQ Lite telah pindah ke isocpp.org/wiki/faq/basics-of-inheritance
avner
134

Anggota publik dari kelas A dapat diakses oleh semua orang.

Anggota yang dilindungi dari kelas A tidak dapat diakses di luar kode A, tetapi dapat diakses dari kode kelas apa pun yang berasal dari A.

Anggota pribadi dari kelas A tidak dapat diakses di luar kode A, atau dari kode kelas apa pun yang berasal dari A.

Jadi, pada akhirnya, memilih antara dilindungi atau pribadi menjawab pertanyaan-pertanyaan berikut: Seberapa banyak kepercayaan yang Anda bersedia untuk dimasukkan ke dalam programmer dari kelas turunan?

Secara default , anggap kelas turunan tidak dapat dipercaya, dan jadikan anggota Anda pribadi . Jika Anda memiliki alasan yang sangat bagus untuk memberikan akses gratis internal kelas ibu ke kelas turunannya, maka Anda dapat membuatnya terlindungi.

paercebal
sumber
Kelas turunan harus merupakan jenis kelas Anda, dan data yang dilindungi dari kelas dasar adalah bagian dari data kelas turunan. Penulis dari kelas turunan diharapkan untuk menangani data ini dengan benar atau itu adalah bug. Namun, data pribadi dalam kelas dasar adalah sesuatu yang tidak dikontrol oleh penulis kelas turunan.
CashCow
@CashCow the protected data of the base class is part of the data of the derived class.Memang. Maka, bukankah lebih baik untuk memiliki penulis dari kelas turunan menyatakan bahwa data di kelas mereka, bukan milikku? ... :-) ... The writer of the derived class is expected to handle this data properly or it is a bug.Dalam pola NVI, tujuannya adalah untuk menjadikan semuanya pribadi, termasuk metode, untuk membatasi kerusakan yang bisa dilakukan penulis kelas turunan ke hierarki. Metode yang dilindungi sudah merupakan masalah potensial. Saya tidak yakin memperparah ini dengan menggunakan negara yang dilindungi adalah pendekatan yang tepat.
paercebal
Bisa jadi, yang mengharuskan Anda untuk memiliki "getter" virtual di kelas dasar untuk mengaksesnya. Dan sementara Anda dapat memiliki di antara kelas untuk melakukan berbagai cara pola data dapat diimplementasikan, itu tidak selalu praktis untuk melakukannya. Misalnya, "pola", umum dalam bahasa yang tidak memiliki pengubah "const" walaupun sebagian besar waktu dalam C ++ tidak diperlukan adalah memiliki kelas dasar hanya baca dan kelas turunan yang dapat ditulis. Dalam C ++ ini juga bisa menyenangkan hanya karena Anda ingin lebih dari satu cara yang mungkin untuk memuat (menginisialisasi) data.
CashCow
Ada berbagai cara untuk melakukan itu. Buat kelas serialisasi Anda menjadi teman. Masukkan semua data Anda ke dalam struct dengan akses publik tetapi kelas Anda memiliki anggota pribadi dari variabel ini .... Anggota yang dilindungi dan kelas turunan untuk memuatnya dari sumber apa pun yang terkadang lebih mudah.
CashCow
63

Anggota yang dilindungi dapat diakses dari kelas turunan. Pribadi tidak.

class Base {

private: 
  int MyPrivateInt;
protected: 
  int MyProtectedInt;
public:
  int MyPublicInt;
};

class Derived : Base
{
public:
  int foo1()  { return MyPrivateInt;} // Won't compile!
  int foo2()  { return MyProtectedInt;} // OK  
  int foo3()  { return MyPublicInt;} // OK
};‌‌

class Unrelated 
{
private:
  Base B;
public:
  int foo1()  { return B.MyPrivateInt;} // Won't compile!
  int foo2()  { return B.MyProtectedInt;} // Won't compile
  int foo3()  { return B.MyPublicInt;} // OK
};

Dalam hal "praktik terbaik", itu tergantung. Jika ada kemungkinan samar bahwa seseorang mungkin ingin mendapatkan kelas baru dari kelas Anda yang sudah ada dan membutuhkan akses ke anggota internal, buat mereka Terlindungi, bukan Pribadi. Jika bersifat pribadi, kelas Anda mungkin menjadi sulit untuk diwariskan dengan mudah.

Roddy
sumber
3
Saya mohon berbeda: jika ada kemungkinan samar bahwa tidak ada subclass yang akan membutuhkannya, jadikan itu pribadi. Kecuali Anda bermaksud membuat subkelas, gunakan pola metode templat.
xtofl
23

Alasan mengapa MFC mendukung dilindungi, adalah karena itu adalah kerangka kerja. Anda mungkin ingin mensubkelas kelas MFC dan dalam hal itu antarmuka yang terproteksi diperlukan untuk mengakses metode yang tidak terlihat oleh penggunaan umum kelas tersebut.

Toon Krijthe
sumber
9

Itu semua tergantung pada apa yang ingin Anda lakukan, dan apa yang Anda inginkan agar kelas turunan dapat melihatnya.

class A
{
private:
    int _privInt = 0;
    int privFunc(){return 0;}
    virtual int privVirtFunc(){return 0;}
protected:
    int _protInt = 0;
    int protFunc(){return 0;}
public:
    int _publInt = 0;
    int publFunc()
    {
         return privVirtFunc();
    }
};

class B : public A
{
private:
    virtual int privVirtFunc(){return 1;}
public:
    void func()
    {
        _privInt = 1; // wont work
        _protInt = 1; // will work
        _publInt = 1; // will work
        privFunc(); // wont work
        privVirtFunc(); // wont work
        protFunc(); // will work
        publFunc(); // will return 1 since it's overridden in this class
    }
}
Mats Fredriksson
sumber
6

Atribut dan metode yang ditandai sebagai protected- tidak seperti yang pribadi - masih terlihat di subclass.

Kecuali jika Anda tidak ingin menggunakan atau memberikan kemungkinan untuk mengganti metode dalam subkelas yang mungkin, saya akan membuatnya private.

fhe
sumber
2
Kelas turunan dapat mengesampingkan fungsi virtual pribadi basisnya
James Hopkin
6

Lihatlah pertanyaan Variabel Anggota yang Dilindungi . Disarankan untuk menggunakan private sebagai default (seperti C ++ classses do) untuk mengurangi coupling. Variabel anggota yang dilindungi adalah ide yang paling buruk, fungsi anggota yang dilindungi dapat digunakan untuk misalnya pola Metode Templat.

xtofl
sumber
Lucu, saya mengeditnya di posting saya sebelum melihat milik Anda. Terpilih karena burung-burung dari bulu menemukan tautan yang sama :)
Firas Assaad
4

Anggota yang dilindungi hanya dapat diakses oleh keturunan kelas, dan dengan kode di modul yang sama. Anggota pribadi hanya dapat diakses oleh kelas tempat mereka dideklarasikan, dan dengan kode dalam modul yang sama.

Tentu saja fungsi teman membuang ini ke luar jendela, tapi oh well.

Ignacio Vazquez-Abrams
sumber
4

anggota pribadi hanya dapat diakses dari dalam kelas, anggota yang dilindungi dapat diakses di kelas dan kelas turunan. Ini adalah fitur warisan dalam bahasa OO.

Anda dapat memiliki warisan pribadi, dilindungi, dan publik dalam C ++, yang akan menentukan kelas turunan apa yang dapat diakses dalam hierarki warisan. C # misalnya hanya memiliki warisan publik.

PhilGriffin
sumber
3

private = hanya dapat diakses oleh induk (kelas dasar) (yaitu hanya orang tua saya yang bisa masuk ke kamar orang tua saya)

terlindung = dapat diakses oleh induk (kelas dasar), dan anak perempuannya (yaitu hanya orang tua saya yang bisa masuk ke kamar orang tua saya, tetapi memberikan izin putra / putri untuk masuk ke kamar orang tua)

publik = dapat diakses oleh induk (kelas dasar), anak perempuan, dan semua orang lainnya (yaitu hanya orang tua saya yang bisa masuk ke kamar orang tua saya, tetapi ini pesta rumah - mi casa su casa)

Johan K. Rhodes
sumber
2

Karena tidak ada fungsi anggota publik yang diperlukan untuk mengambil dan memperbarui anggota yang dilindungi di kelas turunan, ini meningkatkan efisiensi kode dan mengurangi jumlah kode yang perlu kita tulis. Namun, programmer dari kelas turunan seharusnya mengetahui apa yang dia lakukan.

batal
sumber
Anda selalu dapat menggunakan fungsi sebaris yang diterapkan dalam deklarasi kelas. Kompiler akan mengoptimalkan itu jauh (dan itu akan menjadi cara yang baik untuk menegakkan akses read-only ke variabel anggota pribadi, misalnya).
Paul Sanders
2

privatelebih disukai untuk data anggota. Anggota dalam kelas C ++ secara privatedefault.

publiclebih disukai untuk fungsi anggota, meskipun itu masalah pendapat. Setidaknya beberapa metode harus dapat diakses. publicdapat diakses oleh semua. Ini adalah opsi yang paling fleksibel dan paling tidak aman. Siapa saja dapat menggunakannya, dan siapa pun dapat menyalahgunakannya.

privatesama sekali tidak dapat diakses. Tidak ada yang bisa menggunakannya di luar kelas, dan tidak ada yang bisa menyalahgunakan mereka. Bahkan di kelas turunan.

protectedadalah kompromi karena dapat digunakan dalam kelas turunan. Ketika Anda berasal dari kelas, Anda memiliki pemahaman yang baik tentang kelas dasar, dan Anda berhati-hati untuk tidak menyalahgunakan anggota ini.

MFC adalah pembungkus C ++ untuk Windows API, ia lebih suka publicdan protected. Kelas yang dihasilkan oleh Visual Studio penyihir memiliki campuran jelek protected, publicdan privateanggota. Tetapi ada beberapa logika untuk kelas MFC sendiri.

Anggota seperti SetWindowTextitu publickarena Anda sering perlu mengakses anggota ini.

Anggota seperti OnLButtonDown, menangani notifikasi yang diterima oleh jendela. Mereka tidak boleh diakses, oleh karena itu merekaprotected . Anda masih dapat mengaksesnya di kelas turunan untuk mengabaikan fungsi-fungsi ini.

Beberapa anggota harus melakukan utas dan loop pesan, mereka tidak boleh diakses atau diganti, sehingga mereka dinyatakan sebagai private

Dalam struktur C ++, anggota secara publicdefault. Struktur biasanya digunakan hanya untuk data, bukan metode, oleh karena itu publicdeklarasi dianggap aman.

Barmak Shemirani
sumber
1
Anda menulis "Anggota dalam kelas C ++ dilindungi secara default". Menurut standar, mereka adalah pribadi atau publik secara default, tergantung pada kata kunci mana yang digunakan dalam definisi (14p3). Apakah Microsoft menyimpang dari standar di sini?
Alexander Klauer
@AlexanderKlauer Saya salah, secara privatedefault di Visual Studio. Secara privatedefault di gcc juga, tidak pernah publicsecara default. Kecuali saya salah lagi. Saya tidak dapat menemukan standar yang Anda maksud.
Barmak Shemirani
Maaf, saya seharusnya lebih spesifik. Saya mengacu pada standar C ++ 17. Standar C ++ 11 memiliki kata-kata yang sama di 11p3. Bisakah Anda memperbarui jawaban Anda? Terima kasih!
Alexander Klauer
1

Anggota pribadi hanya dapat diakses di kelas yang sama di mana ia telah menyatakan di mana sebagai anggota yang dilindungi dapat diakses di kelas di mana ia dinyatakan bersama dengan kelas yang diwarisi olehnya.

Gayki
sumber
1
  • Pribadi : Ini adalah penentu akses. Secara default, instance (anggota) variabel atau metode kelas di c ++ / java bersifat pribadi. Selama pewarisan, kode dan data selalu diwariskan tetapi tidak dapat diakses di luar kelas. Kami dapat mendeklarasikan anggota data kami sebagai pribadi sehingga tidak ada yang dapat membuat perubahan langsung ke variabel anggota kami dan kami dapat menyediakan getter dan setter publik untuk mengubah anggota pribadi kami. Dan konsep ini selalu diterapkan dalam aturan bisnis.

  • Dilindungi : Ini juga merupakan penentu akses. Dalam C ++, anggota yang dilindungi dapat diakses di dalam kelas dan ke kelas yang diwarisi tetapi tidak di luar kelas. Di Jawa, anggota yang dilindungi dapat diakses di dalam kelas, ke kelas yang diwariskan serta ke semua kelas dalam paket yang sama.

Tutu Kumari
sumber
0

Anggota kelas dasar yang tidak statis yang dilindungi dapat diakses oleh anggota dan teman dari kelas apa pun yang berasal dari kelas dasar itu dengan menggunakan salah satu dari yang berikut:

  • Pointer ke kelas yang diturunkan secara langsung atau tidak langsung
  • Referensi ke kelas yang diturunkan secara langsung atau tidak langsung
  • Objek dari kelas yang diturunkan secara langsung atau tidak langsung
mujtaba
sumber
0

Pribadi: Dapat diakses oleh fungsi anggota kelas & fungsi teman atau kelas teman. Untuk kelas C ++ ini adalah specifier akses default.

Dilindungi: Dapat diakses oleh fungsi anggota kelas, fungsi teman atau kelas teman & kelas turunan.

  • Anda dapat menjaga variabel atau fungsi anggota kelas (bahkan typedef atau kelas dalam) sebagai pribadi atau dilindungi sesuai kebutuhan Anda.
  • Sebagian besar waktu Anda menyimpan anggota kelas sebagai pribadi dan menambahkan fungsi get / set untuk merangkum. Ini membantu dalam pemeliharaan kode.
  • Umumnya fungsi privat digunakan ketika Anda ingin menjaga fungsi publik Anda tetap modular atau untuk menghilangkan kode berulang daripada menulis seluruh kode menjadi fungsi tunggal. Ini membantu dalam pemeliharaan kode.

Lihat tautan ini untuk detail lebih lanjut.

Darshan Rajgor
sumber
-2

pengubah akses pribadi dan terlindungi adalah satu dan sama saja dengan anggota kelas dasar yang dilindungi dapat diakses di luar ruang lingkup kelas dasar dalam kelas anak (turunan). Ini juga berlaku sama untuk warisan. Tetapi dengan pengubah pribadi anggota kelas dasar hanya dapat diakses dalam lingkup atau kode kelas dasar dan fungsi temannya hanya '' ''

Emmanuel Muniko
sumber
5
Nilai apa yang ditambahkan jawaban Anda di atas jawaban lain?
Hermann Döppes