C++ primer 详解派生类向基类转换的可访问性

派生类向基类转换的可访问性

c++ primer第五版 P544

1.首先谈谈protected作为成员访问符的一个情况。

  • 对类用户不可访问。
  • 对派生类的成员和友元可以访问。
  • 最重要的一条性质
    派生类的成员及友元只能通过派生类对象去访问基类的protected成员,而不能通过基类对象去访问基类的proteced成员。
    即如下代码:
 class Base
{
public:
    void pub_mem();
private:
    char priv_mem;
protected:
    int prot_mem;
};

class Derive :public Base
{
public:
    void f1()
    {
        prot_mem = 0;  //成员函数可以访问基类的public和protected成员
        pub_mem();
    }

    void f2(Derive &d) //可以通过派生类对象去访问基类的protected成员
    {
        d.prot_mem = 0;
    }

    void f3(Base &b) //不可以通过基类对象去访问基类的protected成员
    {
        b.prot_mem = 0;
    }


private:
    int der_priv_mem = prot_mem;
};

也就是说访问基类的protected成员就两种方式。

  • 通过在类内,成员及友元(不是对象)直接访问。下面会讲到
  • 在类内,只能通过派生类对象访问。

2.再谈谈派生列表中的访问说明符。

  • 无影响的内容

访问说明符对于派生类中的成员及友元是否能访问基类中的成员,没有任何影响。

class Base
{
public:
    void pub_mem();
private:
    char priv_mem;
protected:
    int prot_mem;
};

class Derive :private Base     //私有继承
{
public:
    void f1()
    {
        prot_mem = 0; //成员函数可以访问基类的public和protected成员
        pub_mem();
    }
private:
    int der_priv_mem = prot_mem;
};

可以看到,即使是private继承,其派生类中的成员及友元依然可以访问基类中的public,protected成员。当然不可访问private成员。

  • 影响的内容
    影响的内容是
    (1).(类外的)派生类的对象对于基类成员的访问权限(如果在类内成员函数内通过派生类对象访问基类protected成员,这样是可以的,也就是1的情况)。
    (2).还有派生类的再派生类的成员及友元对其直接基类的成员的访问权限。
    (1)代码如下:
class Base
{
public:
    void pub_mem();
private:
    char priv_mem;
protected:
    int prot_mem;
};

class Pub_Derive :public Base
{
public:
    void f1()
    {
        prot_mem = 0; 
        pub_mem();
    }

    void f2(Pub_Derive &d)
    {
        d.prot_mem = 0;
    }


private:
    int der_priv_mem = prot_mem;
};

class Prot_Derive :protected Base
{
public:
    void f1()
    {
        prot_mem = 0; 
        pub_mem();
    }

    void f2(Prot_Derive &d)
    {
        d.prot_mem = 0;
    }


private:
    int der_priv_mem = prot_mem;
};

class Priv_Derive :private Base
{
public:
    void f1()
    {
        prot_mem = 0; 
        pub_mem();
    }

    void f2(Priv_Derive &d)
    {
        d.prot_mem = 0;
    }


private:
    int der_priv_mem = prot_mem;
};
    Pub_Derive pubDerive;
    pubDerive.pub_mem();//正确,public继承 访问基类的public成员
    pubDerive.prot_mem;//错误,public继承 访问基类的protected成员
    pubDerive.priv_mem;//错误,public继承 访问基类的private成员

    Prot_Derive protDerive;
    protDerive.pub_mem();//错误,protected继承 访问基类的public成员
    protDerive.prot_mem;//错误,protected继承 访问基类的protected成员
    protDerive.priv_mem;//错误,protected继承 访问基类的private成员

    Priv_Derive privDerive;
    privDerive.pub_mem();//错误,private继承 访问基类的public成员
    privDerive.prot_mem;//错误,private继承 访问基类的protected成员
    privDerive.priv_mem;//错误,private继承 访问基类的private成员

可以看到,如果我们在这些派生类,去访问基类的protected,public成员是没有任何问题的,即无影响内容中所说的。
而我们在类外定义派生类对象,用这个对象去访问基类的成员,这就和派生列表的访问说明符有关了。

可以这样理解,继承是将基类的内容继承到派生类中,而访问说明符是将这些继承过来的再加上访问性质。

public:遵循基类原有的成员访问说明符,即public protected private继承过来仍然是public protected private。
private:将public和protected变为private,private保持不变。
protected:将public变为protected,private和protected保持不变。

(2)代码如下:

class Pub_derived_from_pub :public Pub_Derive
{
    int use_base(){ return prot_mem; }//正确,因为Pub_Derive是公有继承Base,故基类保护成员prot_mem可访问
};

class Prvi_derived_from_pub :public Priv_Derive
{
    int use_base(){ return prot_mem; }//错误,因为Pub_Derive是私有继承Base,故基类保护成员prot_mem不可访问
};

class Prot_derived_from_pub :public Prot_Derive
{
    int use_base(){ return prot_mem; }//正确,因为Pub_Derive是保护继承Base,故基类保护成员prot_mem不可访问
};

我们这样理解,由于Pub_Derive公有继承Base,那么Base::prot_memPub_Derive中实际上是一个protected成员,那么Pub_Derive的子类就可以在类中直接访问其直接基类即Pub_Derive中的protected成员了。这和第1点讨论的吻合。

同理,由于Priv_Derive私有继承Base,那么Base::prot_memPriv_Derive中实际上是一个private成员,当然无法访问。

同理,由于Prot_Derive保护继承Base,那么Base::prot_memProt_Derive中实际上是一个protected成员,同Pub_Derive

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值