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继承

  1. public继承:不改变继承的成员的在派生类中的访问权限
  2. private继承:将继承的成员在派生类总都定义为private
  3. 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继承影响的是:

  1. 派生类的用户的访问权限
Pub_Derv d1;	//继承自Base的成员访问权限不变
Priv_Derv d2; 	//继承自Base的成员变成private
d1.pub_mem();	//正确:pub_mem在派生类中依然是public
d2.pub_mem();	//错误:pub_mem在派生类中变成了private
  1. 派生类的派生类
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;}
}
  1. 派生类能不能隐式转换为基类
  • 用户:只有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

posted @ 2022-03-04 12:45  咪啪魔女  阅读(28)  评论(0编辑  收藏  举报