15-5 访问控制与继承
public\private\protected成员
访问说明符 | 对类成员 | 对类用户 | 对派生类成员 | 对派生类用户 |
---|---|---|---|---|
public | 可见 | 可见 | 可见 | 可见 |
private | 可见 | 不可见 | 不可见 | 不可见 |
protected | 可见 | 不可见 | 可见 | 基类中:不可见/派生类中:可见 |
对protected最后一点的解释:
-
基类中的protected成员对派生类用户不可见到
-
派生类中的protected成员对派生类用户可见
//考虑一下例子加深理解
class Base{
protected :
int prot_mem; //protected成员
};
class Sneaky : public Base {
friend void clobber(Sneaky &);//能访问Sneaky::prot_mem
friend void clobber(Base &);//不能访问Base::prot_mem
int j; //默认是private
};
//正确:clobber能访问Sneaky对象的private和protected成员
void clobber(Sneaky &s) { s.j = s.prot_mem = 0;}
//错误:clobber不能访问基类Base的protected成员
void clobber(Base &b) { b.port_mem = 0;}
派生类对象只能访问派生类中的protected成员,而不能访问基类对象的protected成员
public\private\protected继承
- public继承:不改变继承的成员的在派生类中的访问权限
- private继承:将继承的成员在派生类总都定义为private
- protected继承:将继承的成员在派生类中都定义为protected
由上节的表格可知,无论是哪种继承,都不会影响派生类的成员对从基类继承来的成员的访问,影响的是派生类用户,以及派生的派生类及其用户,对从基类继承来的成员的访问。(有点拗口)
class Base{
public:
void pub_mem(); //public成员
protected:
int prot_mem; //protected成员
private:
char priv_mem; //private成员
};
struct Pub_Derv : public Base{//不改变访问权限
//正确:基类的protected成员在派生类可见
int f() {return prot_mem;}
//错误:基类的private在派生类不可见
char g() {return priv_mem;}
};
struct Priv_Derv: private Base{
//private不影响派生类对从基类继承来的成员的访问权限
int f1() const {return prot_mem;} //正确
};
是public\protected\private继承影响的是:
- 派生类的用户的访问权限
Pub_Derv d1; //继承自Base的成员访问权限不变
Priv_Derv d2; //继承自Base的成员变成private
d1.pub_mem(); //正确:pub_mem在派生类中依然是public
d2.pub_mem(); //错误:pub_mem在派生类中变成了private
- 派生类的派生类
struct Derived_from_public : public Pub_Derv{
//正确:Base::prot_mem在Pub_Derv中仍是protected的
int use_base() {return prot_mem;}
};
struct Derived_from_private : public Priv_Derv{
//错误:Base::prot_mem在Priv_Derv中是private的
int use_base() {return prot_mem;}
}
- 派生类能不能隐式转换为基类
- 用户:只有public继承时才能转换
- 派生类的成员函数和友元:无论什么继承都行
- 派生类的派生类的成员函数和友元:public继承或者protected继承
友元与继承
友元关系不能传递,类似地,友元关系不能继承
不能继承友元关系;每个类负责控制各自成员的访问权限。
所以,基类的友元可以访问基类成员以及派生类中的基类部分
//Sneaky 是 Base的派生类
class Base{
//添加友元声明
friend class Pal; //Pal在访问Base的派生类时不具有特殊性
protected :
int prot_mem;
};
class Pal{
public :
//正确:Pal是Base的友元
int f(Base b) {return b.prot_mem; }
//错误:Pal不是Base的友元
int f(Sneaky s) {return s.j;}
//对基类的访问是由基类控制,即使是对于派生类的基类部分也是如此
//正确:Pal是Base友元
int f3(Sneaky s) {return s.prot_mem;}
}
改变个别成员的可访问性
有时我们可以改变派生类继承的某个成员的访问级别,用``using`声明
class Base{
public:
int size() const {return n;}
protected:
int n;
};
class Priv_Derived : private Base{
public :
using Base:size;
protected :
using Base::n;
};
由于Priv_Derived是私有继承,所以size和n在Priv_Derived中默认是private
使用using
声明时,变量的访问权限由using
前的访问说明符决定
在本例中Priv_Derived中size是public,n是protected