Bagikan melalui


Kontrol Akses Anggota (C++)

Kontrol akses memungkinkan Anda memisahkan public antarmuka kelas dari private detail implementasi dan protected anggota yang hanya untuk digunakan oleh kelas turunan. Penentu akses berlaku untuk semua anggota yang dideklarasikan setelahnya hingga penentu akses berikutnya ditemui.

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

Akses default berada private di kelas, dan public dalam struct atau union. Penentu akses di kelas dapat digunakan berapa kali dalam urutan apa pun. Alokasi penyimpanan untuk objek jenis kelas bergantung pada implementasi. Namun, kompilator harus menjamin penugasan anggota ke alamat memori yang berturut-turut lebih tinggi antara penentu akses.

Kontrol Akses Anggota

Jenis Akses Makna
private Anggota kelas yang dinyatakan sebagai private hanya dapat digunakan oleh fungsi anggota dan teman (kelas atau fungsi) kelas.
protected Anggota kelas yang dinyatakan dapat protected digunakan oleh fungsi anggota dan teman (kelas atau fungsi) kelas. Selain itu, mereka dapat digunakan oleh kelas yang berasal dari kelas .
public Anggota kelas yang dinyatakan sebagai public dapat digunakan oleh fungsi apa pun.

Kontrol akses membantu mencegah Anda menggunakan objek dengan cara yang tidak dimaksudkan untuk digunakan. Perlindungan ini hilang ketika Anda melakukan konversi jenis eksplisit (cast).

Catatan

Kontrol akses sama-sama berlaku untuk semua nama: fungsi anggota, data anggota, kelas berlapis, dan enumerator.

Kontrol Akses di Kelas Turunan

Dua faktor mengontrol anggota kelas dasar mana yang dapat diakses di kelas turunan; faktor-faktor yang sama ini mengontrol akses ke anggota yang diwariskan di kelas turunan:

  • Apakah kelas turunan mendeklarasikan kelas dasar menggunakan penentu public akses.

  • Apa akses ke anggota berada di kelas dasar.

Tabel berikut menunjukkan interaksi antara faktor-faktor ini dan cara menentukan akses anggota kelas dasar.

Akses Anggota di Kelas Dasar

private protected public
Selalu tidak dapat diakses dengan akses derivasi apa pun private di kelas turunan jika Anda menggunakan private derivasi private di kelas turunan jika Anda menggunakan private derivasi
protected di kelas turunan jika Anda menggunakan protected derivasi protected di kelas turunan jika Anda menggunakan protected derivasi
protected di kelas turunan jika Anda menggunakan public derivasi public di kelas turunan jika Anda menggunakan public derivasi

Contoh berikut mengilustrasikan derivasi akses:

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

Dalam DerivedClass1, fungsi PublicFunc anggota adalah public anggota dan ProtectedFunc merupakan protected anggota karena BaseClass merupakan public kelas dasar. PrivateFunc adalah private untuk BaseClass, dan tidak dapat diakses oleh kelas turunan apa pun.

Dalam DerivedClass2, fungsi PublicFunc dan ProtectedFunc dianggap sebagai private anggota karena BaseClass merupakan private kelas dasar. Sekali lagi, PrivateFunc adalah private , BaseClassdan tidak dapat diakses oleh kelas turunan apa pun.

Anda dapat mendeklarasikan kelas turunan tanpa penentu akses kelas dasar. Dalam kasus seperti itu, derivasi dipertimbangkan private jika deklarasi kelas turunan class menggunakan kata kunci. Derivasi dipertimbangkan public jika deklarasi kelas turunan struct menggunakan kata kunci. Misalnya, kode berikut:

class Derived : Base
...

setara dengan:

class Derived : private Base
...

Demikian pula, kode berikut:

struct Derived : Base
...

setara dengan:

struct Derived : public Base
...

Anggota yang dinyatakan memiliki private akses tidak dapat diakses oleh fungsi atau kelas turunan kecuali fungsi atau kelas tersebut friend dinyatakan menggunakan deklarasi di kelas dasar.

Jenis union tidak dapat memiliki kelas dasar.

Catatan

Saat menentukan private kelas dasar, disarankan untuk secara eksplisit menggunakan private kata kunci sehingga pengguna kelas turunan memahami akses anggota.

Kontrol akses dan anggota statis

Saat Anda menentukan kelas dasar sebagai private, itu hanya memengaruhi anggota nonstatis. Anggota statis publik masih dapat diakses di kelas turunan. Namun, mengakses anggota kelas dasar menggunakan pointer, referensi, atau objek dapat memerlukan konversi, yang menerapkan kontrol akses lagi. Pertimbangkan contoh berikut:

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

Dalam kode sebelumnya, kontrol akses melarang konversi dari penunjuk ke Derived2 penunjuk ke Base. Penunjuk this secara implisit berjenis Derived2 *. Untuk memilih CountOf fungsi, this harus dikonversi ke jenis Base *. Konversi semacam itu tidak diizinkan karena Base merupakan private kelas dasar tidak langsung ke Derived2. Konversi ke private jenis kelas dasar hanya dapat diterima untuk penunjuk ke kelas turunan langsung. Itulah sebabnya penunjuk jenis Derived1 * dapat dikonversi ke jenis Base *.

Panggilan eksplisit ke CountOf fungsi, tanpa menggunakan penunjuk, referensi, atau objek untuk memilihnya, tidak menyiratkan konversi. Itu sebabnya panggilan diizinkan.

Anggota dan teman dari kelas turunan, T, dapat mengonversi penunjuk ke T penunjuk ke private kelas dasar langsung .T

Akses ke fungsi virtual

Kontrol akses yang diterapkan ke virtual fungsi ditentukan oleh jenis yang digunakan untuk melakukan panggilan fungsi. Mengesampingkan deklarasi fungsi tidak memengaruhi kontrol akses untuk jenis tertentu. Contohnya:

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

Dalam contoh sebelumnya, memanggil fungsi GetState virtual menggunakan pointer untuk mengetik VFuncBase panggilan VFuncDerived::GetState, dan GetState diperlakukan sebagai public. Namun, panggilan GetState menggunakan pointer untuk mengetik VFuncDerived adalah pelanggaran kontrol akses karena GetState dinyatakan private di kelas VFuncDerived.

Perhatian

Fungsi GetState virtual dapat dipanggil menggunakan penunjuk ke kelas VFuncBasedasar . Ini tidak berarti bahwa fungsi yang disebut adalah versi kelas dasar dari fungsi tersebut.

Kontrol akses dengan beberapa pewarisan

Dalam latensi multi-pewarisan yang melibatkan kelas dasar virtual, nama tertentu dapat dicapai melalui lebih dari satu jalur. Karena kontrol akses yang berbeda dapat diterapkan di sepanjang jalur yang berbeda ini, pengkompilasi memilih jalur yang memberikan akses terbanyak. Lihat gambar berikut:

Diagram showing access along the paths of an inheritance graph.

Diagram menunjukkan hierarki pewarisan berikut: kelas VBase adalah kelas dasar. Class LeftPath mewarisi dari VBase menggunakan VBase virtual private . kelas RightPath juga mewarisi dari VBase tetapi menggunakan VBase virtual public . Terakhir, kelas Turunan mewarisi dari kelas LeftPath dan kelas RightPath menggunakan public LeftPath, public RightPath.

Mengakses sepanjang jalur grafik pewarisan

Dalam gambar, nama yang dideklarasikan di kelas VBase selalu dicapai melalui kelas RightPath. Jalur yang tepat lebih dapat diakses karena RightPath dinyatakan VBase sebagai public kelas dasar, sementara LeftPath menyatakan VBase sebagai private.

Baca juga

Referensi Bahasa C++