Üye Erişim Denetimi (C++)
Erişim denetimleri, bir sınıfın public
arabirimini uygulama ayrıntılarından ve private
yalnızca türetilmiş sınıflar tarafından kullanılmak üzere olan üyelerden protected
ayırmanızı sağlar. Erişim tanımlayıcısı, sonraki erişim tanımlayıcısı karşılaşılana kadar ondan sonra bildirilen tüm üyeler için geçerlidir.
class Point
{
public:
Point( int, int ) // Declare public constructor.;
Point();// Declare public default constructor.
int &x( int ); // Declare public accessor.
int &y( int ); // Declare public accessor.
private: // Declare private state variables.
int _x;
int _y;
protected: // Declare protected function for derived classes only.
Point ToWindowCoords();
};
Varsayılan erişim bir sınıfta ve private
bir yapı veya birleşimdedirpublic
. Bir sınıftaki erişim tanımlayıcıları herhangi bir sırada istediğiniz sayıda kullanılabilir. Sınıf türlerinin nesneleri için depolama ayırması uygulamaya bağlıdır. Ancak, derleyicilerin erişim tanımlayıcıları arasında ardışık olarak daha yüksek bellek adreslerine üye atamasını garanti etmesi gerekir.
Üye Erişim Denetimi
Erişim Türü | Anlamı |
---|---|
private |
olarak private bildirilen sınıf üyeleri yalnızca sınıfın üye işlevleri ve arkadaşları (sınıflar veya işlevler) tarafından kullanılabilir. |
protected |
olarak protected bildirilen sınıf üyeleri, sınıfın üye işlevleri ve arkadaşları (sınıflar veya işlevler) tarafından kullanılabilir. Ayrıca, sınıfından türetilen sınıflar tarafından kullanılabilir. |
public |
olarak public bildirilen sınıf üyeleri herhangi bir işlev tarafından kullanılabilir. |
Erişim denetimi, nesneleri kullanılmaları amaçlanmamış şekillerde kullanmanızı önlemeye yardımcı olur. Açık tür dönüştürmeleri (yayınlar) yaptığınızda bu koruma kaybolur.
Not
Erişim denetimi tüm adlar için aynı şekilde geçerlidir: üye işlevleri, üye verileri, iç içe geçmiş sınıflar ve numaralandırıcılar.
Türetilmiş Sınıflarda Erişim Denetimi
İki faktör, türetilmiş bir sınıfta temel sınıfın hangi üyelerinin erişilebilir olduğunu denetler; aynı faktörler türetilmiş sınıfta devralınan üyelere erişimi denetler:
Türetilmiş sınıfın erişim tanımlayıcısını kullanarak temel sınıfı bildirip bildirmediği
public
.Üyeye erişimin temel sınıfta ne olduğu.
Aşağıdaki tabloda bu faktörler arasındaki etkileşim ve temel sınıf üye erişiminin nasıl belirleneceği gösterilmektedir.
Temel Sınıfta Üye Erişimi
private |
protected |
public |
---|---|---|
Türetme erişimiyle her zaman erişilemez |
private türetme kullanıyorsanız private türetilmiş sınıfta |
private türetme kullanıyorsanız private türetilmiş sınıfta |
protected türetme kullanıyorsanız protected türetilmiş sınıfta |
protected türetme kullanıyorsanız protected türetilmiş sınıfta |
|
protected türetme kullanıyorsanız public türetilmiş sınıfta |
public türetme kullanıyorsanız public türetilmiş sınıfta |
Aşağıdaki örnekte erişim türetmesi gösterilmektedir:
// access_specifiers_for_base_classes.cpp
class BaseClass
{
public:
int PublicFunc(); // Declare a public member.
protected:
int ProtectedFunc(); // Declare a protected member.
private:
int PrivateFunc(); // Declare a private member.
};
// Declare two classes derived from BaseClass.
class DerivedClass1 : public BaseClass
{
void foo()
{
PublicFunc();
ProtectedFunc();
PrivateFunc(); // function is inaccessible
}
};
class DerivedClass2 : private BaseClass
{
void foo()
{
PublicFunc();
ProtectedFunc();
PrivateFunc(); // function is inaccessible
}
};
int main()
{
DerivedClass1 derived_class1;
DerivedClass2 derived_class2;
derived_class1.PublicFunc();
derived_class2.PublicFunc(); // function is inaccessible
}
'de DerivedClass1
üye işlevi PublicFunc
bir public
üyedir ve ProtectedFunc
bir üyedir protected
çünkü BaseClass
bir temel sınıftır public
.
PrivateFunc
private
, BaseClass
ve türetilmiş sınıflar için erişilemez.
içinde DerivedClass2
ve PublicFunc
işlevleri ProtectedFunc
bir private
temel sınıf olduğundan BaseClass
üye olarak kabul edilirprivate
.
PrivateFunc
Yine , için ve private
BaseClass
türetilmiş sınıflar için erişilemez.
Türetilmiş bir sınıfı temel sınıf erişim tanımlayıcısı olmadan bildirebilirsiniz. Böyle bir durumda türetilmiş sınıf bildirimi anahtar sözcüğünü kullanıyorsa türetme dikkate private
alınırclass
. Türetilmiş sınıf bildirimi anahtar sözcüğünü kullanıyorsa türetme dikkate public
alınırstruct
. Örneğin aşağıdaki kod:
class Derived : Base
...
eşdeğerdir:
class Derived : private Base
...
Benzer şekilde, aşağıdaki kod:
struct Derived : Base
...
eşdeğerdir:
struct Derived : public Base
...
Erişim sahibi private
olarak bildirilen üyeler, bu işlevler veya sınıflar temel sınıfta bildirimi friend
kullanılarak bildirilmediği sürece işlevler veya türetilmiş sınıflar tarafından erişilemez.
Bir union
türün temel sınıfı olamaz.
Not
Bir private temel sınıf belirtirken, türetilmiş sınıfın private
kullanıcılarının üye erişimini anlaması için anahtar sözcüğünü açıkça kullanmanız önerilir.
Erişim denetimi ve statik üyeler
olarak private
bir temel sınıf belirttiğinizde, yalnızca statik olmayan üyeleri etkiler. Türetilmiş sınıflarda genel statik üyelere hâlâ erişilebilir. Ancak, işaretçiler, başvurular veya nesneler kullanarak temel sınıfın üyelerine erişmek için yeniden erişim denetimi uygulayan bir dönüştürme gerekebilir. Aşağıdaki örneği inceleyin:
// access_control.cpp
class Base
{
public:
int Print(); // Nonstatic member.
static int CountOf(); // Static member.
};
// Derived1 declares Base as a private base class.
class Derived1 : private Base
{
};
// Derived2 declares Derived1 as a public base class.
class Derived2 : public Derived1
{
int ShowCount(); // Nonstatic member.
};
// Define ShowCount function for Derived2.
int Derived2::ShowCount()
{
// Call static member function CountOf explicitly.
int cCount = ::Base::CountOf(); // OK.
// Call static member function CountOf using pointer.
cCount = this->CountOf(); // C2247: 'Base::CountOf'
// not accessible because
// 'Derived1' uses 'private'
// to inherit from 'Base'
return cCount;
}
Önceki kodda; erişim denetimi, bir Derived2
işaretçisinden Base
işaretçisine dönüşümü yasaklar. İşaretçi this
örtük olarak türündedir Derived2 *
. İşlevi CountOf
seçmek için türüne this
Base *
dönüştürülmelidir. için dolaylı bir temel sınıf olduğundan Base
böyle bir private dönüştürmeye Derived2
izin verilmez. Temel sınıf türüne private dönüştürme yalnızca hemen türetilen sınıflara yönelik işaretçiler için kabul edilebilir. Bu nedenle tür Derived1 *
işaretçileri türüne Base *
dönüştürülebilir.
İşlevi seçmek için CountOf
işaretçi, başvuru veya nesne kullanmadan yapılan açık çağrı, dönüştürme olmadığını gösterir. Bu nedenle aramaya izin verilir.
türetilmiş bir sınıfın üyeleri ve arkadaşları, T
işaretçiyi T
doğrudan temel sınıfına privateT
dönüştürebilir.
Sanal işlevlere erişim
İşlevlere virtual
uygulanan erişim denetimi, işlev çağrısını yapmak için kullanılan türe göre belirlenir. İşlev bildirimlerini geçersiz kılma, belirli bir türün erişim denetimini etkilemez. Örneğin:
// access_to_virtual_functions.cpp
class VFuncBase
{
public:
virtual int GetState() { return _state; }
protected:
int _state;
};
class VFuncDerived : public VFuncBase
{
private:
int GetState() { return _state; }
};
int main()
{
VFuncDerived vfd; // Object of derived type.
VFuncBase *pvfb = &vfd; // Pointer to base type.
VFuncDerived *pvfd = &vfd; // Pointer to derived type.
int State;
State = pvfb->GetState(); // GetState is public.
State = pvfd->GetState(); // C2248 error expected; GetState is private;
}
Yukarıdaki örnekte, yazmak GetState
için bir işaretçi kullanarak sanal işlevi VFuncBase
çağırmak öğesini çağırır VFuncDerived::GetState
ve GetState
olarak public
değerlendirilir. Ancak, türünde GetState
bir işaretçi kullanılarak çağrılmasıVFuncDerived
, sınıfında GetState
bildirildiği private
için VFuncDerived
erişim denetimi ihlalidir.
Dikkat
GetState
sanal işlevi, VFuncBase
temel sınıfının işaretçisi kullanılarak çağrılabilir. Bu, çağrılan işlevin bu işlevin temel sınıf sürümü olduğu anlamına gelmez.
Birden çok devralma ile erişim denetimi
Sanal temel sınıflar içeren birden çok devralma kafeslerinde, belirli bir ada birden fazla yolla ulaşılabilir. Bu farklı yollarda farklı erişim denetimi uygulanabileceği için derleyici en çok erişimi sağlayan yolu seçer. Aşağıdaki şekilde bakın:
Diyagramda şu devralma hiyerarşisi gösterilmektedir: VBase sınıfı temel sınıftır. Sınıf LeftPath, sanal private VBase kullanarak VBase'den devralır. sınıfı RightPath de VBase'den devralır ancak sanal public VBase kullanır. Son olarak, Türetilen sınıfı LeftPath ve RightPath sınıfından LeftPath, public RightPath kullanarak public devralır.
Devralma grafiğinin yollarına erişme
Şekilde VBase
sınıfında bildirilen bir ada her zaman RightPath
sınıfıyla ulaşılır. Doğru yol daha erişilebilir çünkü RightPath
temel sınıf olarak VBase
bildirirken public
LeftPath
olarak VBase
bildirirprivate
.