řízení přístupu ke členu (C++)
Řízení přístupu umožňuje oddělit public
rozhraní třídy od private
podrobností implementace a protected
členů, které jsou pouze pro použití odvozenými třídami. Specifikátor přístupu se vztahuje na všechny členy deklarované za ním, dokud nebude zjištěn další specifikátor přístupu.
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();
};
Výchozí přístup je private
ve třídě a public
ve struktuře nebo sjednocení. Specifikátory přístupu ve třídě lze použít libovolný počet v libovolném pořadí. Přidělení úložiště pro objekty typů tříd je závislé na implementaci. Kompilátory však musí zaručit přiřazení členů k následným vyšším adresům paměti mezi specifikátory přístupu.
Ovládací prvek přístupu členů
Typ přístupu | Význam |
---|---|
private |
Členy třídy deklarované jako private mohou být používány pouze členské funkce a přátelé (třídy nebo funkce) třídy. |
protected |
Členy třídy deklarované jako protected mohou být používány členské funkce a přátelé (třídy nebo funkce) třídy. Navíc je možné je použít třídami odvozenými z třídy. |
public |
Členy třídy deklarované jako public mohou být použity libovolnou funkcí. |
Řízení přístupu pomáhá zabránit tomu, abyste používali objekty způsobem, který by se neměl použít. Tato ochrana se ztratí, když provedete explicitní převody typu (přetypování).
Poznámka
Řízení přístupu se vztahuje rovněž na všechny názvy: členské funkce, data členů, vnořené třídy a enumerátory.
Řízení přístupu v odvozených třídách
Dva faktory řídí, které členy základní třídy jsou přístupné v odvozené třídě; tyto stejné faktory řídí přístup ke zděděným členům v odvozené třídě:
Zda odvozená třída deklaruje základní třídu pomocí specifikátoru
public
přístupu.Jaký je přístup k členu v základní třídě.
Následující tabulka ukazuje interakci mezi těmito faktory a určením přístupu členů základní třídy.
Přístup člena v základní třídě
private |
protected |
public |
---|---|---|
Vždy nepřístupný s jakýmkoli přístupem k odvození | private v odvozené třídě, pokud používáte private odvození |
private v odvozené třídě, pokud používáte private odvození |
protected v odvozené třídě, pokud používáte protected odvození |
protected v odvozené třídě, pokud používáte protected odvození |
|
protected v odvozené třídě, pokud používáte public odvození |
public v odvozené třídě, pokud používáte public odvození |
Následující příklad znázorňuje odvození přístupu:
// 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
}
V DerivedClass1
, člen funkce PublicFunc
je public
člen a ProtectedFunc
je protected
člen, protože BaseClass
je public
základní třída. PrivateFunc
je private
pro BaseClass
všechny odvozené třídy nepřístupné.
V DerivedClass2
, funkce PublicFunc
a ProtectedFunc
jsou považovány za private
členy, protože BaseClass
je private
základní třída. Opět platí, PrivateFunc
že je private
BaseClass
nepřístupný pro všechny odvozené třídy.
Odvozenou třídu můžete deklarovat bez specifikátoru přístupu základní třídy. V takovém případě se odvození považuje private
za předpokladu, že deklarace odvozené třídy používá class
klíčové slovo. Odvození je považováno public
za předpokladu struct
, že deklarace odvozené třídy používá klíčové slovo. Například následující kód:
class Derived : Base
...
odpovídá:
class Derived : private Base
...
Podobně platí následující kód:
struct Derived : Base
...
odpovídá:
struct Derived : public Base
...
Členy deklarované jako přístup private
nejsou přístupné pro funkce nebo odvozené třídy, pokud tyto funkce nebo třídy nejsou deklarovány pomocí friend
deklarace v základní třídě.
Typ union
nemůže mít základní třídu.
Poznámka
Při zadávání private základní třídy je vhodné explicitně použít private
klíčové slovo, aby uživatelé odvozené třídy porozuměli přístupu člena.
Řízení přístupu a statické členy
Když zadáte základní třídu jako private
, má vliv pouze na nestatické členy. Veřejné statické členy jsou v odvozených třídách stále přístupné. Přístup ke členům základní třídy pomocí ukazatelů, odkazů nebo objektů však může vyžadovat převod, který znovu použije řízení přístupu. Představte si následující příklad:
// 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;
}
V předchozím kódu řízení přístupu zakazuje převod z ukazatele na typ Derived2
na ukazatele na typ Base
. Ukazatel this
je implicitně typu Derived2 *
. Chcete-li vybrat CountOf
funkci, this
musí být převedena na typ Base *
. Takový převod není povolen, protože Base
je nepřímá private základní třída do Derived2
. Převod na private typ základní třídy je přijatelný pouze pro ukazatele na okamžité odvozené třídy. Proto lze ukazatele typu Derived1 *
převést na typ Base *
.
Explicitní volání CountOf
funkce bez použití ukazatele, odkazu nebo objektu k jeho výběru neznamená žádný převod. Proto je hovor povolený.
Členové a přátelé odvozené třídy , T
mohou převést ukazatel na T
ukazatel private na přímý základní třídy .T
Přístup k virtuálním funkcím
Řízení přístupu použité u virtual
funkcí je určeno typem použitým k volání funkce. Přepsání deklarací funkce nemá vliv na řízení přístupu pro daný typ. Příklad:
// 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;
}
V předchozím příkladu volání virtuální funkce GetState
pomocí ukazatele na typ VFuncBase
volání VFuncDerived::GetState
a GetState
je považován za public
. Volání GetState
pomocí ukazatele na typ VFuncDerived
je však porušení řízení přístupu, protože GetState
je deklarováno private
ve třídě VFuncDerived
.
Upozornění
Virtuální funkci GetState
lze zavolat pomocí ukazatele na základní třídu VFuncBase
. To neznamená, že volána funkce je verze této funkce základní třídy.
Řízení přístupu s více dědičností
Ve svazech vícenásobné dědičnosti zahrnujících virtuální základní třídy lze konkrétního názvu dosáhnout více cestami. Protože v případě těchto různých cest mohou platit různá řízení přístupu, volí kompilátor volí, která poskytuje nejvíce přístupu. Podívejte se na následující obrázek:
Diagram znázorňuje následující hierarchii dědičnosti: třída VBase je základní třída. Třída LeftPath dědí z VBase pomocí virtuálního private VBase. Třída RightPath také dědí z VBase, ale používá virtuální public VBase. Nakonec třída Odvozená dědí z třídy LeftPath i třídy RightPath pomocí public LeftPath, public RightPath.
Přístup k cestám grafu dědičnosti
Na obrázku je název deklarovaný ve třídě VBase
vždy dosažen prostřednictvím třídy RightPath
. Správná cesta je přístupnější, protože RightPath
deklaruje VBase
jako public
základní třídu, zatímco LeftPath
deklaruje VBase
jako private
.
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro