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
, BaseClass
dan 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 VFuncBase
dasar . 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 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
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk