Özel ve Korumalı Üyeler: C ++


276

Birisi arasındaki farka olarak aydınlatmak bana privateve protectedüyeler sınıflarında?

En iyi uygulama sözleşmelerinden, sınıf dışında çağrılmayan değişkenlerin ve işlevlerin yapılması gerektiğini anlıyorum private- ancak MFC projeme bakıldığında , MFC'nin lehine olduğu anlaşılıyor protected.

Fark nedir ve hangisini kullanmalıyım?

Yanıtlar:


374

Özel üyelere sadece onları tanımlayan sınıf içinde erişilebilir.

Korunan üyelere kendilerini tanımlayan sınıfta ve o sınıftan miras alan sınıflarda erişilebilir.

Düzenleme: Her ikisine de kendi sınıflarındaki arkadaşlar ve korunan üyeler söz konusu olduğunda, türetilmiş sınıflarının arkadaşları tarafından erişilebilir.

Edit 2: Sorununuz bağlamında anlamlı olan her şeyi kullanın. Kuplajı azaltmak ve temel sınıfın uygulanmasını korumak için mümkün olduğunda üyeleri özel yapmaya çalışmalısınız, ancak bu mümkün değilse korumalı üyeleri kullanın. Kontrol C ++ SSS konunun daha iyi anlaşılması için. Korunan değişkenler hakkındaki bu soru da yardımcı olabilir.


12
C ++ FAQ Lite bağlantısı isocpp.org/wiki/faq/basics-of-inheritance
avner

134

A sınıfının herkese açık üyeleri herkese açıktır.

A sınıfının korumalı üyelerine A kodunun dışında erişilemez, ancak A'dan türetilen herhangi bir sınıfın kodundan erişilebilir.

A sınıfının özel üyelerine A kodunun dışında veya A'dan türetilen herhangi bir sınıfın kodundan erişilemez.

Sonuçta, korumalı veya özel arasında seçim yapmak aşağıdaki soruları cevaplıyor: Türetilmiş sınıfın programcısına ne kadar güvenmek istiyorsunuz?

Varsayılan olarak , türetilmiş sınıfa güvenilmeyeceğini varsayın ve üyelerinizi özel yapın . Ana sınıfın iç kısımlarına türetilmiş sınıflarına ücretsiz erişim vermek için çok iyi bir nedeniniz varsa, onları koruyabilirsiniz.


Türetilmiş sınıf, sınıfınızın bir türü olmalıdır ve temel sınıfın korunan verileri, türetilmiş sınıfın verilerinin bir parçasıdır. Türetilmiş sınıfın yazarının bu verileri düzgün işlemesi ya da bir hatadır. Ancak bir temel sınıftaki özel veriler, türetilmiş sınıfın yazarının kontrol etmediği bir şeydir.
CashCow

@CashCow the protected data of the base class is part of the data of the derived class.Gerçekten. Öyleyse, türetilmiş sınıfın yazarının verileri benim yerine sınıflarında bildirmesini sağlamak daha iyi değil mi? ... :-) ... The writer of the derived class is expected to handle this data properly or it is a bug.NVI deseninde amaç, aşağıdakileri de içeren her şeyi özel yapmaktır. türetilmiş sınıf yazarının hiyerarşiye verebileceği zararı sınırlamak için yöntemler Korumalı yöntemler zaten potansiyel bir sorundur. Korumalı devlet kullanarak bunu ağırlaştırmaya ikna olmadım doğru yaklaşım.
paercebal

Bu, erişmek için temel sınıfta sanal "alıcılar" olmasını gerektirebilir. Veri deseninin uygulanabileceği farklı yolları yapmak için sınıflar arasında olabilirken, bunu yapmak her zaman pratik değildir. Örneğin, "const" değiştiricisi olmayan dillerde yaygın olan bir "kalıp", C ++ 'da çoğu zaman gerekli olmasa da, salt okunur bir temel sınıf ve yazılabilir türetilmiş sınıflara sahip olmaktır. C ++ 'da bu da güzel olabilir çünkü verileri yüklemek (başlatmak) için birden fazla olası yol istiyorsanız.
CashCow

Bunu yapmanın çeşitli yolları vardır. Serileştirme sınıflarınızı arkadaş edin. Tüm verilerinizi genel erişime sahip bir yapıya koyun, ancak sınıfınızda bu değişkenin özel bir üyesi var ... Korunan üyeler ve türetilmiş sınıflar, bazen daha kolay olan herhangi bir kaynaktan yüklemek için.
CashCow

63

Korunan üyelere türetilmiş sınıflardan erişilebilir. Özel olanlar yapamaz.

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
};

"En iyi uygulama" açısından, duruma göre değişir. Birisinin mevcut sınıfınızdan yeni bir sınıf türetmek isteyebileceği ve dahili üyelere erişmesi gerekebileceğine dair zayıf bir olasılık bile varsa, bunları Özel değil Korumalı hale getirin. Eğer özel iseler, sınıfınızı kolayca miras almak zor olabilir.


3
Farklı olmaya yalvarıyorum: Eğer hiçbir alt sınıfın buna ihtiyaç duymayacağına dair zayıf bir olasılık varsa, onu özel yapın. Eğer sürece niyetinde sınıf sınıflandırma etmiş, Kalıp yönteminin.
xtofl

23

MFC'nin korumayı tercih etmesinin nedeni, bir çerçeve olmasıdır. Muhtemelen MFC sınıflarını alt sınıflara ayırmak istersiniz ve bu durumda sınıfın genel kullanımı tarafından görülemeyen yöntemlere erişmek için korumalı bir arabirim gerekir.


9

Her şey ne yapmak istediğinize ve türetilmiş sınıfların neyi görebilmesini istediğinize bağlıdır.

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
    }
}

6

Olarak işaretlenmiş öznitelikler ve yöntemler protectedÖzel aksine - hala alt sınıflarda görünür.

Olası alt sınıflarda yöntemi geçersiz kılma veya kullanma olasılığını sağlamadığınız sürece, bunları yapardım private.


2
Türetilmiş bir sınıf, üssünün özel sanal işlevlerini geçersiz kılabilir
James Hopkin

6

Korumalı Üye Değişkenleri sorusuna bir göz atın . classKuplajı azaltmak için özel olarak varsayılan olarak (C ++ ses'in yaptığı gibi) kullanılması önerilir . Korunan üye değişkenler her zaman kötü bir fikirdir, örneğin Korunan Yöntem yöntemi için korunan üye işlevleri kullanılabilir.


Komik, sizinkini görmeden önce bunu yazıma düzenledim. Aynı bağlantı üzerine bir kuş tüyü var çünkü :)
Firas Assaad

4

Korunan üyelere yalnızca sınıfın torunları ve aynı modüldeki kod ile erişilebilir. Özel üyelere yalnızca bildirildikleri sınıf ve aynı modüldeki kod ile erişilebilir.

Tabii ki arkadaş işlevleri bunu pencereden dışarı atıyor, ama iyi.


4

özel üyelere sadece sınıf içinden erişilebilir, korunan üyelere sınıfta ve türetilmiş sınıflarda erişilebilir. OO dillerinde kalıtımın bir özelliği.

Türetilmiş sınıfların kalıtım hiyerarşisinde nelere erişebileceğini belirleyen C ++ 'da özel, korumalı ve genel mirasa sahip olabilirsiniz. Örneğin C # sadece genel mirasa sahiptir.


3

private = yalnızca annelik (temel sınıf) tarafından erişilebilir (yani yalnızca ebeveynim ebeveynimin yatak odasına girebilir)

Korumalı = annelik (temel sınıf) ve kızları tarafından erişilebilir (yani sadece ebeveynim ebeveynimin yatak odasına gidebilir, ancak oğul / kıza ebeveyn yatak odasına girme izni verdi)

public = annelik (ana sınıf), kızı ve diğer herkes tarafından erişilebilir (yani sadece ebeveynim ebeveynimin yatak odasına girebilir, ancak bu bir ev partisi - mi casa su casa)


2

Türetilmiş sınıfta korumalı üyeleri almak ve güncellemek için herhangi bir genel üye işlevi gerekmediğinden, bu kodun verimliliğini artırır ve yazmamız gereken kod miktarını azaltır. Ancak, türetilmiş sınıfın programcısının ne yaptığının farkında olması gerekir.


Her zaman sınıf bildiriminde uygulanan bir satır içi işlevi kullanabilirsiniz. Derleyici bunu optimize eder (örneğin, özel bir üye değişkenine salt okunur erişimi zorlamanın iyi bir yolu olabilir).
Paul Sanders

2

privateüye verileri için tercih edilir. C ++ sınıflarındaki üyeler privatevarsayılan olarak vardır.

publicüye işlevleri için tercih edilir, ancak bu bir görüş meselesidir. En azından bazı yöntemlere erişilebilir olmalıdır. publicherkese açıktır. En esnek ve en az güvenli seçenektir. Onları herkes kullanabilir ve herkes onları kötüye kullanabilir.

privateerişilemez. Kimse onları sınıf dışında kullanamaz ve kimse onları kötüye kullanamaz. Türetilmiş sınıflarda bile.

protectedbir uzlaşmadır çünkü türetilmiş sınıflarda kullanılabilir. Bir sınıftan türettiğinizde, temel sınıfı iyi anlarsınız ve bu üyeleri kötüye kullanmamaya dikkat edersiniz.

MFC, Windows API için bir C ++ sarmalayıcısıdır publicve tercih eder protected. Visual Studio tarafından oluşturulan Sınıflar çirkin bir karışımı var Sihirbazı protected, publicveprivate üyeleri. Ancak MFC sınıflarının kendileri için bir mantık var.

Üye gibi SetWindowTextolan publicsık sık bu üyeleri erişmek gerekir çünkü.

OnLButtonDownPencereden alınan bildirimleri işlemek gibi üyeler . Bunlara erişilmemelidir, bu yüzden erişirler protected. Bu işlevleri geçersiz kılmak için bunlara yine de türetilmiş sınıfta erişebilirsiniz.

Bazı üyeler ileti dizileri ve ileti döngüleri yapmak zorundadır, erişilmemeli veya geçersiz kılmamalıdır, bu nedenle private

C ++ yapılarında, üyeler publicvarsayılan olarak vardır. Yapılar genellikle sadece veriler için kullanılır, yöntemler için kullanılmaz, bu nedenle publicbildirim güvenli kabul edilir.


1
"C ++ sınıflarındaki üyeler varsayılan olarak korunur" yazarsınız. Standarda göre, tanımda hangi anahtar kelimenin kullanıldığına bağlı olarak varsayılan olarak özel veya herkese açıktır (14p3). Microsoft buradaki standarttan sapıyor mu?
Alexander Klauer

@AlexanderKlauer Yanılmışım, privatevarsayılan olarak Visual Studio'da. Bu var privateo asla yanı gcc varsayılan olarak publicvarsayılan. Tekrar yanılmıyorsam. Bahsettiğiniz standardı bulamıyorum.
Barmak Shemirani

Üzgünüm, daha spesifik olmalıydım. C ++ 17 standardına atıfta bulunuyordum. C ++ 11 standardı, 11p3'te aynı ifadeye sahiptir. Cevabınızı güncelleyebilir misiniz? Teşekkürler!
Alexander Klauer

1

Özel üyeye yalnızca, korunan üyeye kendisinden miras alınan sınıflarla birlikte bildirildiği sınıfta erişilebileceği bildirildiği sınıfta erişilebilir.


1
  • Özel : Bir erişim belirtecidir. Varsayılan olarak, örnek (üye) değişkenleri veya c ++ / java içindeki bir sınıfın yöntemleri özeldir. Kalıtım sırasında, kod ve veriler her zaman miras alınır ancak sınıfın dışında erişilebilir değildir. Veri üyelerimizi özel olarak ilan edebiliriz, böylece hiç kimse üye değişkenlerimizde doğrudan değişiklik yapamaz ve özel üyelerimizi değiştirmek için kamu alıcıları ve belirleyiciler sağlayabiliriz. Ve bu kavram her zaman iş kuralında uygulanır.

  • Korumalı : Aynı zamanda bir erişim belirtecidir. C ++ 'da, korunan üyelere sınıf içinde ve miras alınan sınıf tarafından erişilebilir, ancak sınıfın dışında erişilemez. Java'da, korunan üyelere sınıf içinde, miras alınan sınıfa ve aynı paket içindeki tüm sınıflara erişilebilir.


0

Korumalı statik olmayan bir temel sınıf üyesine, bu temel sınıftan türetilen herhangi bir sınıfın üyeleri ve arkadaşları aşağıdakilerden birini kullanarak erişebilir:

  • Doğrudan veya dolaylı olarak türetilmiş bir sınıfa işaretçi
  • Doğrudan veya dolaylı olarak türetilmiş bir sınıfa başvuru
  • Doğrudan veya dolaylı olarak türetilmiş bir sınıfın nesnesi

0

Özel: Sınıf üyesi işlevleri ve arkadaş işlevi veya arkadaş sınıfı tarafından erişilebilir. C ++ sınıfı için bu varsayılan erişim belirleyicisidir.

Korumalı: Sınıf üyesi işlevleri, arkadaş işlevi veya arkadaş sınıfı ve türetilmiş sınıflar tarafından erişilebilir.

  • Sınıf üyesi değişkenini veya işlevini (typedefs veya iç sınıflar bile) özel veya gereksiniminize göre korunmuş olarak tutabilirsiniz.
  • Çoğu zaman sınıf üyesini özel olarak tutar ve kapsüllemek için get / set işlevleri eklersiniz. Bu, kodun korunmasına yardımcı olur.
  • Genel olarak özel işlev, genel işlevlerinizi modüler tutmak veya tüm kodu tek bir işleve yazmak yerine tekrarlanan kodu ortadan kaldırmak istediğinizde kullanılır. Bu, kodun korunmasına yardımcı olur.

Daha fazla ayrıntı için bu bağlantıya bakın .


-2

özel ve korumalı erişim değiştiricileri yalnızca taban sınıfın korumalı üyelerine alt (türetilmiş) sınıftaki taban sınıfın kapsamı dışında erişilebilecek bir ve aynıdır. Aynısı kalıtım için de geçerlidir. Ancak özel değiştirici ile temel sınıfın üyelerine sadece temel sınıfın kapsamı veya kodu ile erişilebilir ve yalnızca arkadaş işlevleri '' ''


5
Cevabınız diğer cevaplara ne katıyor?
Hermann Döppes
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.