Arasındaki fark nedir
public
,private
veprotected
de miras C ++?
SO'da bulduğum tüm sorular belirli vakalarla ilgileniyor.
Arasındaki fark nedir
public
,private
veprotected
de miras C ++?
SO'da bulduğum tüm sorular belirli vakalarla ilgileniyor.
Yanıtlar:
Bu soruyu cevaplamak için önce üye erişimcilerini kendi kelimelerimle tanımlamak istiyorum. Bunu zaten biliyorsanız, "next:" başlığına atlayın.
Orada Bildiğim üç erişimciler şunlardır: public
, protected
ve private
.
İzin Vermek:
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
Base
de farkındadır .Base
publicMember
Base
içerir protectedMember
.Base
farkında değil privateMember
."Farkında" demekle "varlığını kabul etmeyi ve dolayısıyla erişebilmeyi" kastediyorum.
Aynı şey kamu, özel ve korunmuş miras için de geçerlidir. Bir sınıfı Base
ve Child
miras kalan bir sınıfı ele alalım Base
.
public
, farkında olan Base
ve Child
bunun da Child
miras olduğunun farkında olan her şey Base
.protected
sadece Child
ve çocuklarıysa, miras aldıklarının farkındadırlar Base
.private
, mirastan başka kimse Child
bilmez.SomeBase
anonim bir tür üyesini oluşturmak için nasıl zor kodlanmış bir yol gibi olduğunu gösteren başka bir durumdur SomeBase
. Bu, diğer tüm üyeler gibi, aynı erişimi harici erişim üzerinde kullanan bir erişim belirtecine sahiptir.
class A
{
public:
int x;
protected:
int y;
private:
int z;
};
class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};
class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};
class D : private A // 'private' is default for classes
{
// x is private
// y is private
// z is not accessible from D
};
ÖNEMLİ NOT: B, C ve D sınıflarının tümü x, y ve z değişkenlerini içerir. Bu sadece erişim meselesidir.
Korumalı ve özel miras kullanımı hakkında burada okuyabilirsiniz .
Kalıtımın görünürlüğünü sınırlamak, kodun bazı sınıfların başka bir sınıfı miras aldığını görememesini sağlar: Türetilmiş olandan tabana örtülü dönüşümler işe yaramaz ve static_cast
tabandan türetilene kadar da çalışmaz.
Yalnızca bir sınıfın üyeleri / arkadaşları özel kalıtım görebilir ve yalnızca üyeler / arkadaşlar ve türetilmiş sınıflar korumalı kalıtım görebilir.
halk mirası
IS-A mirası. Düğme - bir penceredir ve bir pencerenin gerekli olduğu herhangi bir yerde, bir düğme de geçirilebilir.
class button : public window { };
korumalı kalıtım
Korumalı-terimler-içinde-uygulanır. Nadiren kullanışlıdır. Kullanılan boost::compressed_pair
(Aşağıdaki örnek noktasında olmaya devam şablonu kullanmaz) boş taban sınıfı optimizasyonu kullanarak boş sınıflardan ve bellek tasarrufu türetmek için:
struct empty_pair_impl : protected empty_class_1
{ non_empty_class_2 second; };
struct pair : private empty_pair_impl {
non_empty_class_2 &second() {
return this->second;
}
empty_class_1 &first() {
return *this; // notice we return *this!
}
};
özel miras
Uygulanan-terimler-in. Temel sınıfın kullanımı yalnızca türetilmiş sınıfın uygulanması içindir. Özelliklerle ve boyut önemliyse kullanışlıdır (yalnızca işlevler içeren boş özellikler, boş temel sınıf optimizasyonundan faydalanır). Bununla birlikte, genellikle muhafaza daha iyi bir çözümdür. Dizelerin boyutu kritiktir, bu yüzden burada sık görülen bir kullanımdır
template<typename StorageModel>
struct string : private StorageModel {
public:
void realloc() {
// uses inherited function
StorageModel::realloc();
}
};
kamu üyesi
toplam
class pair {
public:
First first;
Second second;
};
Erişimciler
class window {
public:
int getWidth() const;
};
korunan üye
Türetilmiş sınıflar için gelişmiş erişim sağlama
class stack {
protected:
vector<element> c;
};
class window {
protected:
void registerClass(window_descriptor w);
};
özel üye
Uygulama ayrıntılarını sakla
class window {
private:
int width;
};
C-stil dökümlerin, türetilmiş bir sınıfın korumalı veya özel bir temel sınıfa tanımlanmış ve güvenli bir şekilde dökülmesine ve diğer yöne de dökülmesine izin verdiğini unutmayın. Her ne pahasına olursa olsun bundan kaçınılmalıdır, çünkü kodu uygulama ayrıntılarına bağlı hale getirebilir - ancak gerekirse bu tekniği kullanabilirsiniz.
Bu üç anahtar kelime, görünürlük devralma modelini belirtmek için tamamen farklı bir bağlamda da kullanılır .
Bu tablo, alt sınıf tamamen tanımlandığında bileşenlere sonuç olarak erişilmesini sağlayan bileşen bildirimi ve miras modelinin tüm olası birleşimlerini toplar.
Yukarıdaki tablo aşağıdaki şekilde yorumlanmıştır (ilk satıra bir göz atın):
Bir bileşen ise beyan olarak kamuoyuna ve sınıf edilir miras olarak kamuoyuna çıkan erişim olduğunu kamu .
Bir örnek:
class Super {
public: int p;
private: int q;
protected: int r;
};
class Sub : private Super {};
class Subsub : public Sub {};
Değişkenler için çıkan erişim p
, q
, r
sınıfta Subsub olduğu hiçbiri .
Başka bir örnek:
class Super {
private: int x;
protected: int y;
public: int z;
};
class Sub : protected Super {};
Değişkenler için çıkan erişim y
, z
sınıf içinde Sub edilir korumalı ve değişken için x
olan yok .
Daha ayrıntılı bir örnek:
class Super {
private:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
int main(void) {
Super object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
Şimdi bir alt sınıf tanımlayalım:
class Sub : Super { };
int main(void) {
Sub object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
Ad adlı bir sınıfın alt sınıfı olan Sub adlı tanımlı sınıf Super
, Sub
sınıftan türetilir Super
. Sub
Yeni değişkenler ne de yeni fonksiyonlar ne sınıf tanıtır. Sub
Sınıfın herhangi bir nesnesinin, sınıfın Super
aslında bir Super
sınıfın nesnelerinin bir kopyası olması sonrasında tüm özellikleri miras aldığı anlamına mı geliyor ?
Hayır . Öyle değil.
Aşağıdaki kodu derlersek, derleme hatalarından başka bir şey elde edemeyiz put
ve derleme hataları ve get
yöntemlere erişilemez. Neden?
Görünürlük belirtecini atladığımızda, derleyici özel miras olarak adlandırılacağımızı varsayar . Bu, tüm genel üst sınıf bileşenlerinin özel erişime dönüştüğü , özel üst sınıf bileşenlerine erişilemeyeceği anlamına gelir . Sonuç olarak, alt sınıfın içinde ikincisini kullanma izniniz olmadığı anlamına gelir.
Derleyiciye önceden kullanılan erişim politikasını korumak istediğimizi bildirmeliyiz.
class Sub : public Super { };
Yanlış yönlendirmeyin : bu, Super sınıfının özel bileşenlerinin (depolama değişkeni gibi) biraz büyülü bir şekilde herkese açık hale geleceği anlamına gelmez. Özel bileşenler kalacaktır özel , kamu kalacaktır kamu .
Sub
Sınıftaki nesneler, sınıftan yarattıkları büyük kardeşleriyle "neredeyse" aynı şeyleri yapabilir Super
. "Neredeyse" çünkü bir alt sınıf olması, sınıfın üst sınıfın özel bileşenlerine erişimi kaybettiği anlamına da gelir . Sub
Depolama değişkenini doğrudan işleyebilecek sınıfın üye işlevini yazamıyoruz .
Bu çok ciddi bir kısıtlama. Herhangi bir çözüm var mı?
Evet .
Üçüncü erişim seviyesine korumalı denir . Korumalı anahtar kelime, onunla işaretlenen bileşenin , alt sınıflardan herhangi biri tarafından kullanıldığında genel bir bileşen gibi davrandığı ve dünyanın geri kalanına özel bir bileşen gibi göründüğü anlamına gelir . - Bu yalnızca herkese açık olarak devralınan sınıflar için geçerlidir (örneğimizdeki Süper sınıf gibi) -
class Super {
protected:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
class Sub : public Super {
public:
void print(void) {cout << "storage = " << storage;}
};
int main(void) {
Sub object;
object.put(100);
object.put(object.get() + 1);
object.print();
return 0;
}
Örnek kodda gördüğünüz gibi, Sub
sınıfa yeni bir işlevsellik kazandırır ve önemli bir şey yapar: depolama sınıfına Super sınıfından erişir .
Değişkenin özel olarak bildirilmesi mümkün olmazdı. Ana işlev kapsamında değişken yine de gizli kalır, böylece şöyle bir şey yazarsanız:
object.storage = 0;
Derleyici bunun bir olduğunu bildirecektir error: 'int Super::storage' is protected
.
Son olarak, son program aşağıdaki çıktıyı üretecektir:
storage = 101
Temel sınıfın kamu üyelerinin türetilmiş sınıftan nasıl açığa çıkmalarıyla ilgilidir.
Litb'in işaret ettiği gibi, kamu mirası çoğu programlama dilinde göreceğiniz geleneksel mirastır. Yani "IS-A" ilişkisini modeller. Özel kalıtım, AFAIK C ++ 'a özgü bir şey, "ŞARTLARDA UYGULANAN" bir ilişkidir. Yani türetilmiş sınıfta ortak arabirimi kullanmak istiyorsunuz , ancak türetilmiş sınıf kullanıcısının bu arabirime erişmesini istemiyorsunuz. Birçoğu, bu durumda, temel sınıfı özel bir temel olarak kullanmak yerine, temel sınıfı bir araya getirmeniz gerektiğini, temel sınıfın işlevselliğini yeniden kullanmak için türetilmiş bir üye oluşturduğunu iddia eder.
Member in base class : Private Protected Public
Kalıtım türü : Nesne şu şekilde miras alınır :
Private : Inaccessible Private Private
Protected : Inaccessible Protected Protected
Public : Inaccessible Protected Public
1) Kamu Mirası :
a. Temel sınıftaki özel üyelere Türetilmiş sınıfta erişilemez.
b. Base sınıfının korumalı üyeleri Derived sınıfında korunur.
c. Temel sınıfın kamu üyeleri Türetilmiş sınıfta kamuya açıktır.
Böylece, diğer sınıflar Temel sınıfın ortak üyelerini Derived sınıf nesnesi aracılığıyla kullanabilir.
2) Korumalı Kalıtım :
a. Temel sınıftaki özel üyelere Türetilmiş sınıfta erişilemez.
b. Base sınıfının korumalı üyeleri Derived sınıfında korunur.
c. Temel sınıfın kamu üyeleri de Türetilmiş sınıfın korunan üyeleri haline gelir.
Bu nedenle, diğer sınıflar Temel sınıfın ortak üyelerini Derived sınıf nesnesi aracılığıyla kullanamaz; ancak Derived'in alt sınıfında kullanılabilirler.
3) Özel Miras :
a. Temel sınıftaki özel üyelere Türetilmiş sınıfta erişilemez.
b. Base sınıfının korunan ve kamu mensupları Derived sınıfının özel üyeleri olurlar.
Bu nedenle, Base sınıfının hiçbir üyesine, Derived sınıfında özel oldukları için Derived sınıf nesnesi aracılığıyla diğer sınıflar tarafından erişilemez. Böylece, Türetilmiş sınıfın alt sınıfı bile onlara erişemez.
Kamu kalıtımı bir IS-A ilişkisini modeller. İle
class B {};
class D : public B {};
her D
biri bir B
.
Özel miras IS-UYGULANAN-KULLANMA ilişkisini (veya ne denirse) modeller. İle
class B {};
class D : private B {};
Bir D
olduğu değil bir B
, ama her D
Kullanımları B
uygulanmasında. Özel kalıtım her zaman kısıtlama kullanılarak ortadan kaldırılabilir:
class B {};
class D {
private:
B b_;
};
Bu D
da, B
bu durumda onun kullanılarak uygulanabilir b_
. Muhafaza, türler arasında kalıtımdan daha az sıkı bir bağlantıdır, bu nedenle genel olarak tercih edilmelidir. Bazen özel miras yerine çevreleme kullanmak özel miras kadar uygun değildir. Genellikle tembel olmak için topal bir bahane.
Kimsenin hangi protected
miras modellerini bildiğini sanmıyorum . En azından henüz ikna edici bir açıklama görmedim.
D
özel olarak türetilirse D
, sanal işlevlerini geçersiz kılabilir B
. (Örneğin, B
bir gözlemci arabirimiyse, o zaman D
bunu uygulayabilir ve this
herkes D
bir gözlemci olarak kullanamadan bir arabirim gerektiren işlevlere geçebilir .) Ayrıca, D
seçerek B
arabirimindeki üyeleri seçerek kullanılabilir hale getirebilir using B::member
. Her ikisi de B
bir üye olduğunda sözdizimi açısından elverişsizdir .
protected
kalıtım Bir virtual
temel sınıf ve protected
ctor ile yararlı buldum :struct CommonStuff { CommonStuff(Stuff*) {/* assert !=0 */ } }; struct HandlerMixin1 : protected virtual CommonStuff { protected: HandlerMixin1() : CommonStuff(nullptr) {} /*...*/ }; struct Handler : HandlerMixin1, ... { Handler(Stuff& stuff) : CommonStuff(&stuff) {} };
Herkese açık olarak başka bir sınıftan miras alırsanız, herkes miras aldığınızı bilir ve bir temel sınıf işaretçisi aracılığıyla herkes tarafından polimorfik olarak kullanılabilir.
Korumalı olarak miras alırsanız, sadece çocuk sınıflarınız sizi polimorfik olarak kullanabilir.
Özel olarak miras alırsanız, yalnızca kendiniz üst sınıf yöntemlerini uygulayabilirsiniz.
Temel olarak, sınıfların geri kalanının ana sınıfınızla olan ilişkiniz hakkındaki bilgilerini sembolize eder.
Korumalı veri üyelerine, sınıfınızdan devralınan herhangi bir sınıf tarafından erişilebilir. Ancak özel veri üyeleri bunu yapamazlar. Diyelim ki aşağıdakiler var:
class MyClass {
private:
int myPrivateMember; // lol
protected:
int myProtectedMember;
};
Uzantınızdan bu sınıfa kadar gönderme this.myPrivateMember
işe yaramaz. Ancak, this.myProtectedMember
olacak. Değer hala kapsüllenir, bu nedenle bu sınıfın bir örneğine sahipsek myObj
, o myObj.myProtectedMember
zaman işe yaramaz, bu nedenle işlevde özel bir veri üyesine benzer.
Accessors | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public | y | y | y
—————————————+————————————+———————————————+———————
protected | y | y | n
—————————————+————————————+———————————————+———————
private | | |
or | y | n | n
no accessor | | |
y: accessible
n: not accessible
Java için bu örneğe dayanarak ... Bence bin kelimeye bedel küçük bir tablo :)
Özet:
Devralınırken, (bazı dillerde) bir veri üyesinin koruma türünü belirli bir yönde, örneğin korumalıdan herkese açık olarak değiştirebilirsiniz.
Bir temel sınıfın özel üyelerine yalnızca o temel sınıfın üyeleri erişebilir.
Bir temel sınıfın kamu üyelerine, o temel sınıfın üyeleri, türetilmiş sınıfın üyeleri ve temel sınıf ve türetilmiş sınıfın dışındaki üyeler tarafından erişilebilir.
Bir temel sınıfın korunan üyelerine, temel sınıfın üyeleri ve ayrıca türetilmiş sınıfın üyeleri tarafından erişilebilir.
özel : temel
korumalı : baz + türetilmiş
public : base + türetilmiş + diğer herhangi bir üye
Kolay bir cevap buldum ve gelecekteki referansım için de göndermeyi düşündüm.
Http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/ bağlantılarından
class Base
{
public:
int m_nPublic; // can be accessed by anybody
private:
int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
int m_nProtected; // can be accessed by Base member functions, or derived classes.
};
class Derived: public Base
{
public:
Derived()
{
// Derived's access to Base members is not influenced by the type of inheritance used,
// so the following is always true:
m_nPublic = 1; // allowed: can access public base members from derived class
m_nPrivate = 2; // not allowed: can not access private base members from derived class
m_nProtected = 3; // allowed: can access protected base members from derived class
}
};
int main()
{
Base cBase;
cBase.m_nPublic = 1; // allowed: can access public members from outside class
cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}
Temelde, türetilmiş sınıftaki temel sınıfın kamusal ve korunan üyelerinin erişim korumasıdır. Toplumsal kalıtımla, türetilmiş sınıf üssün kamusal ve korunan üyelerini görebilir. Özel miras ile olamaz. Korumalı olarak, türetilmiş sınıf ve bundan türetilmiş sınıflar onları görebilir.