一:成員的訪問權限
1: public訪問權限
一個類的public成員變量、成員函數,可以通過類的成員函數、類的實例變量進行訪問
<實際上,類的成員函數,可以訪問本類內的任何成員變量和成員函數>
#include<iostream>
#include<string>
using namespace std;
class AccessTest
{
public:
int pub_mem;
int pub_fun(){};
protected:
int prot_mem;
int prot_fun(){};
private:
int priv_memb;
int priv_fun(){};
};
int main()
{
AccessTest at;
at.pub_mem; //OK, 類變量可以訪問public成員
at.pub_func(); //OK, 訪問public成員函數是沒有問題的
return 0;
}
2:protected訪問權限
一個類的protected成員變量、成員函數,無法通過類的實例變量進行訪問。但是可以通過類的友元函數、友元類進行訪問。
#include<string>
#include<iostream>
using namespace std;
class AccessTest
{
friend void Atest();
friend class CAtest;
public:
int pub_mem;
void pub_fun(){}
protected:
int prot_mem;
void prot_fun(){}
private:
int priv_memb;
void priv_fun(){}
};
class CAtest
{
public:
void x()
{
AccessTest t;
t.prot_fun(); //OK,友元類可以訪問protected成員函數
int x=t.prot_mem; //OK,友元類可以訪問protected成員變量
}
};
void Atest()
{
AccessTest t;
t.prot_fun(); //OK,友元函數可以訪問protected成員函數
int x=t.prot_mem; //OK,友元函數可以訪問protected成員變量
}
int main()
{
AccessTest at;
at.prot_mem; //ERROR,類實例變量無法訪問protected成員變量
at.prot_fun(); //ERROR,類實例變量無法訪問protected成員函數
Atest();
return 0;
}
3:private訪問權限
一個類的private成員變量、成員函數,無法通過類的實例變量進行訪問。但是可以通過類的友元函數、友元類進行訪問。
#include<iostream>
#include<string>
using namespace std;
class AccessTest
{
friend void Atest();
friend class CAtest;
public:
int pub_mem;
void pub_fun(){}
protected:
int prot_mem;
void prot_fun(){}
private:
int priv_memb;
void priv_fun(){}
};
class CAtest
{
public:
void x()
{
AccessTest t;
t.priv_fun(); //OK,友元類可以訪問private成員函數
int x=t.priv_memb; //OK,友元類可以訪問private成員變量
}
};
void Atest()
{
AccessTest t;
t.priv_fun(); //OK,友元函數可以訪問private成員函數
int x=t.priv_memb; //OK,友元函數可以訪問private成員變量
}
int main()
{
AccessTest at;
at.priv_memb; //ERROR,類實例變量無法訪問private成員變量
at.priv_fun(); //ERROR,類實例變量無法訪問private成員函數
Atest();
return 0;
}
到現在,是否感覺私有訪問屬性,和保護屬性沒有什麼區別?區別主要體現在繼承上面。下面將會講到。
總結:public在任何地方都能訪問,protected只能在派生類中訪問, private只能在友元中訪問。
二:繼承的訪問權限控制
1:public繼承
派生類通過public繼承,基類的各種權限不變 。
派生類的成員函數,可以訪問基類的public成員、protected成員,但是無法訪問基類的private成員。
派生類的實例變量,可以訪問基類的public成員,但是無法訪問protected、private成員,彷彿基類的成員之間加到了派生類一般。
可以將public繼承看成派生類將基類的public,protected成員囊括到派生類,但是不包括private成員。
#include<iostream>
#include<string>
using namespace std;
class AccessTest
{
public:
int pub_mem;
void pub_fun(){}
protected:
int prot_mem;
void prot_fun(){}
private:
int priv_memb;
void priv_fun(){}
};
class DAccessTest:public AccessTest
{
public:
void test()
{
int x=pub_mem; //OK
pub_fun(); //OK
int y=prot_mem; //OK
prot_fun(); //OK
int z=priv_memb; //ERROR
priv_fun(); //ERROR
}
};
int main()
{
DAccessTest dt;
int x=dt.pub_mem; //OK
int y=dt.prot_mem; //ERROR
int z=dt.priv_memb; //ERROR
return 0;
}
2:protected繼承
派生類通過protected繼承,基類的public成員在派生類中的權限變成了protected 。protected和private不變。
派生類的成員函數,可以訪問基類的public成員、protected成員,但是無法訪問基類的private成員。
派生類的實例變量,無法訪問基類的任何成員,因爲基類的public成員在派生類中變成了protected。
可以將protected繼承看成派生類將基類的public,protected成員囊括到派生類,全部作爲派生類的protected成員,但是不包括private成員。
private成員是基類內部的隱私,除了友元,所有人員都不得窺探。派生類的友元,都不能訪問
#include<iostream>
#include<string>
using namespace std;
class AccessTest
{
friend void Atest();
friend class CAtest;
public:
int pub_mem;
void pub_fun(){}
protected:
int prot_mem;
void prot_fun(){}
private:
int priv_memb;
void priv_fun(){}
};
class DAccessTest:protected AccessTest
{
public:
void test()
{
int x=pub_mem; //OK
pub_fun(); //OK
int y=prot_mem; //OK
prot_fun(); //OK
int z=priv_memb; //ERROR
priv_fun(); //ERROR
}
};
int main()
{
DAccessTest dt;
int x=dt.pub_mem; //ERROR,基類的成員現在是派生類的保護成員
int y=dt.prot_mem; //ERROR,基類的成員現在是派生類的保護成員
int z=dt.priv_memb; //ERROR
return 0;
}
3:private繼承
派生類通過private繼承,基類的所有成員在派生類中的權限變成了private。
派生類的成員函數,可以訪問基類的public成員、protected成員,但是無法訪問基類的private成員。
派生類的實例變量,無法訪問基類的任何成員,因爲基類的所有成員在派生類中變成了private。
可以將private繼承看成派生類將基類的public,protected成員囊括到派生類,全部作爲派生類的private成員,但是不包括private成員。
private成員是基類內部的隱私,除了友元,所有人員都不得窺探。派生類的友元,都不能訪問
#include<iostream>
#include<string>
using namespace std;
class AccessTest
{
friend void Atest();
friend class CAtest;
public:
int pub_mem;
void pub_fun(){}
protected:
int prot_mem;
void prot_fun(){}
private:
int priv_memb;
void priv_fun(){}
};
class DAccessTest:private AccessTest
{
public:
void test()
{
int x=pub_mem; //OK
pub_fun(); //OK
int y=prot_mem; //OK
prot_fun(); //OK
int z=priv_memb; //ERROR
priv_fun(); //ERROR
}
};
int main()
{
DAccessTest dt;
int x=dt.pub_mem; //ERROR,基類的成員現在是派生類的私有成員
int y=dt.prot_mem; //ERROR,基類的成員現在是派生類的私有成員
int z=dt.priv_memb; //ERROR, private成員無法訪問
return 0;
}
總結:繼承修飾符,就像是一種篩子,將基類的成員篩到派生類。public、protected、private,就是篩子的眼。
通過public繼承,所有基類成員(除了private),public、protected都到了派生類裏面,public篩眼比較大,不會改變訪問權限。
通過protected繼承,所有基類成員(除了private),public、protected都到了派生類裏面,protected篩眼大小適中,所有過來的成員都變成了protected。
通過private繼承,所有基類成員(除了private),public、protected都到了派生類裏面,private篩眼最小,所有過來的成員都變成了private。
PS:關於class和struct的區別
1:class不寫修飾符,成員默認是private的,而struct 默認是public的
class Base //默認private
{
int a;
int b;
}
Base ba;
int x=ba.a;//錯誤
int y=ba.b;//錯誤
struct St //默認public
{
int a;
int b;
};
St st;
int x=st.a; //OK
int y=st.b;//OK
2:class的繼承默認是private的,而struct默認是public的
class Base{...};
class Derive:Base{...} //private繼承
struct BStruct{...};
struct DStruct:BStruct{...};//public繼承