派生类向基类转换的可访问性
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_mem
在Pub_Derive
中实际上是一个protected成员,那么Pub_Derive
的子类就可以在类中直接访问其直接基类即Pub_Derive
中的protected成员了。这和第1点讨论的吻合。
同理,由于Priv_Derive
私有继承Base
,那么Base::prot_mem
在Priv_Derive
中实际上是一个private成员,当然无法访问。
同理,由于Prot_Derive
保护继承Base
,那么Base::prot_mem
在Prot_Derive
中实际上是一个protected成员,同Pub_Derive
。