Sdílet prostřednictvím


ří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 BaseClassvš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 privateBaseClassnepří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 , Tmohou 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::GetStatea 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 showing access along the paths of an inheritance graph.

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é

Referenční dokumentace jazyka C++