C++知识点46——类继承中的类型转换与访问权限控制(中)
接上一篇文章https://blog.csdn.net/Master_Cui/article/details/109741735
四、public继承、protected继承和private继承
子类对继承的成员的访问权限受两个因素影响,第一个是继承成员在基类中的访问权限说明符,第二个是派生列表中的访问权限说明符。
派生列表的访问说明符的作用是:控制子类中的基类成员的访问权限。
如果是public继承,基类中的成员在子类中的访问权限不变(无法将protected和private变为public,因为会破坏封装)
如果是protected继承,基类中public成员在子类中的访问权限变为protected
如果是private继承,基类中public和protected成员在子类中的访问权限均变为private
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
int bpub;
protected:
int bpro;
private:
int bpri;
};
struct derive: base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void pubfunc() {bpub=10;}
void profunc() {bpro=10;}
};
int main(int argc, char const *argv[])
{
derive t;
t.bpub=10;
//t.bpro=10;
return 0;
}
上述代码必须将第28行注释掉,因为是public继承,使用子类时,基类中成员在子类中的访问权限不变,所以无法在子类中访问private成员,也无法在其他作用域访问protected成员
此外,第15行也说明:如果不指定派生列表访问说明符,那么使用struct定义的类的默认的派生列表访问说明符是public
示例2:protected继承
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
int bpub;
protected:
int bpro;
private:
int bpri;
};
struct derive:protected base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void pubfunc() {bpub=10;}
void profunc() {bpro=10;}
};
int main(int argc, char const *argv[])
{
derive t;
//t.bpub=10;
//t.bpro=10;
return 0;
}
上述代码必须将第27,28行注释掉,否则会出现如下错误
因为是protected继承,所以,使用子类时,基类中的public成员在子类中的访问权限变为protected,此时,只有子类成员和友元可以访问,所以无法在子类以外的其他作用域(比如main)访问
示例3:private继承
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
int bpub;
protected:
int bpro;
private:
int bpri;
};
class derive:base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void pubfunc() {bpub=10;}
void profunc() {bpro=10;}
};
int main(int argc, char const *argv[])
{
derive t;
t.bpub=10;
t.bpro=10;
return 0;
}
使用private继承时,道理同protected继承,在使用子类时,bpub和bpro都变成了子类的private成员,所以无法访问bpub和bpro
此外,第15行也说明:如果不指定派生列表访问说明符,那么使用class定义的类的默认的派生列表访问说明符是private
派生列表访问说明符不仅可以控制子类用户对于基类成员的访问权限,还可以控制继承子类的新子类的访问权限
示例
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
int bpub;
protected:
int bpro;
private:
int bpri;
};
struct derive:private base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void pubfunc() {bpub=10;}
void profunc() {bpro=10;}
};
class derive2:public derive
{
public:
derive2(){cout<<__func__<<endl;}
~derive2(){cout<<__func__<<endl;}
void d2pubfunc() {bpub=10;}
void d2profunc() {bpro=10;}
};
上述代码之所以无法编译通过,是因为derive private继承base,所以base中的public和protected成员都变成了private,而derive2继承derive后,访问了derive中的private成员,所以编译失败
所以,如果一个子类是private继承某个基类,那么就不要使用该子类作为其他新子类的基类,因为该子类中的大部分成员都是不可见的
派生列表的访问说明符不影响子类的成员和友元直接访问基类成员。
也就是说,无论哪种继承方式,子类对象都能访问父类的public和protected成员
示例
class base
{
public:
base(){cout<<__func__<<endl;}
~base(){cout<<__func__<<endl;}
int bpub;
protected:
int bpro;
private:
int bpri;
};
struct derive: private base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
void pubfunc() {bpub=10;}
void profunc() {bpro=10;}
//void prifunc(derive &d) {d.bpri=10;}
};
上述代码中无论子类继承基类的方式是啥,都不能违背子类对象可以在子类中可以访问父类的public和protected成员,但是不能访问private成员这一原则。
此外,无论是继承方式是啥,除private之外的可访问的基类成员最终都可以在子类中访问(因为继承后,可访问的基类的成员的访问权限无非就是public,protected和private)
所以,综合以上两点,可以编译成功。
参考
《C++ Primer》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出
上一篇: 面向对象知识点4
下一篇: Spring-ioc快速入门详解01