接上一篇文章https://blog.csdn.net/Master_Cui/article/details/109768311

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

当一个子类向基类转化时:有以下三条规则:

1、只有子类public继承基类时,用户代码(比如main函数)才能将子类转为基类,如果是protected或者private继承,则用户代码无法完成转化

示例

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 d;base b=d;base *pb=new derive();base &rb=d;return 0;
}

编译时出现了3条错误:个人理解原因如下:

因为基类指针或引用指向了一个子类对象,又因为protected继承的原因,子类中,基类的public成员就都变成protected成员,而使用基类指针只能访问基类的成员,不能访问子类的成员,所以此时基类的指针或者引用无法访问基类中的任何对象,所以,这种情况下,反正基类啥也访问不到,定义了也没啥用,编译器干脆报错。所以,在用户代码中,当子类protected或者private继承基类时,不允许使用基类的指针或引用指向子类对象

正因为在用户代码中,当子类protected或者private继承基类时,不允许使用基类的指针或引用指向子类对象,而base b=d;时,会调用base的拷贝构造函数,拷贝构造的形参就是const base &,所以,不允许传参,所以,在用户代码中,当子类protected或者private继承基类时,不能使用子类对基类进行拷贝初始化或者operator=

private继承同理

第一条归根结底的原因是:protected或者private继承使得基类中的成员在子类中的访问权限发生变化,而使得基类对象无法在用户代码中访问自己的成员

2.无论子类用什么方式继承基类,子类的友元和成员都能使用子类向基类的转化,子类向直接基类的类型转换对于子类的成员和友元都是可以访问的

示例

class base
{
public:base(){cout<<__func__<<endl;}~base(){cout<<__func__<<endl;}void func(base &t) {t.bpro=10;}int bpub;protected:int bpro;private:int bpri;
};struct derive:private base
{
public:derive(){cout<<__func__<<endl;}~derive(){cout<<__func__<<endl;}void pubfunc() {derive d;base *pb=new derive();base &rb=d;base b=d;b.func(b);b.bpub=10;bpro=10;//pb->bpro=10;//rb.bpro=10;}
};

无论derive如何继承base,上述代码都可可已编译通过的。

个人理解原因:因为无论derive如何继承base,无论base中的成员在子类中因为继承的方式的不同访问权限变成了啥,base中的成员都是子类derive的一部分,所以,子类derive一定能访问到base中可访问的成员,所以,允许,无论继承方式如何,都允许在在子类的对象和友元进行子类到基类的转化

所以,第二点归根结底是因为无论子类成员的访问权限是啥,子类对象都能在类内和友元内对子类可访问的成员进行访问

3.如果子类protected或者public继承基类,那么子类的子类的成员和友元可以使用子类向基类的转换,如果子类private继承基类,子类的子类的成员和友元就不能使用子类向基类的转换

示例

class base
{
public:base(){cout<<__func__<<endl;}~base(){cout<<__func__<<endl;}void func(base &t) {t.bpro=10;}int bpub;protected:int bpro;private:int bpri;
};struct derive:private base
{
public:derive(){cout<<__func__<<endl;}~derive(){cout<<__func__<<endl;}void pubfunc() {derive d;base *pb=new derive();base &rb=d;base b=d;b.func(b);b.bpub=10;bpro=10;//pb->bpro=10;//rb.bpro=10;}
};class derive2:public derive
{
public:derive2(){cout<<__func__<<endl;}~derive2(){cout<<__func__<<endl;}void d2test() {derive d;base b=d;base *pb=new derive();base &rb=d;b.func(b);//d.bpro=10;}
};

出现了好多不可访问错误

个人理解原因:因为struct derive:private base,所以在子类derive中的base成员都是private的,所以当derive2继承derive时,在类内访问了基类derive中的private成员,所以报错

归根结底还是因为private继承改变了基类的成员的访问权限

如果是protected继承,那么在子类derive中的base的非private成员都是protected的,当derive2继承derive时,在类内访问了基类derive中的protected成员,所以OK

六、改变个别成员的可访问性

通过在类内部使用using关键字,可将子类的基类中的可访问成员标记为public,protected和private。从而可以将可访问成员的访问权限人为修改,而不用根据继承方式决定

示例

class base
{
public:base(){cout<<__func__<<endl;}~base(){cout<<__func__<<endl;}void func(base &t) {t.bpro=10;}int bpub;protected:int bpro;private:int bpri;
};struct derive:public base
{
public:derive(){cout<<__func__<<endl;}~derive(){cout<<__func__<<endl;}void pubfunc() {derive d;base *pb=new derive();base &rb=d;base b=d;b.func(b);b.bpub=10;bpro=10;//pb->bpro=10;//rb.bpro=10;}using base::bpro;protected:using base::func;private:using base::bpub;
};int main(int argc, char const *argv[])
{derive d;d.bpub=10;return 0;
}

可见,将bpub的访问权限修改为private后,bpub在main中不可见了

参考

《C++ Primer》

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

C++知识点47——类继承中的类型转换与访问权限控制(下)相关推荐

  1. C++知识点45——类继承中的类型转换与访问权限控制(上)

    一.类的继承与类型转换 1.概述 一般情况,如果想把一个类的指针或引用绑定到另外一个对象上,需要指针或者引用的类型与指向对象一致.但是存在继承关系的类是个例外:可以将基类的指针或者引用指向子类 原因是 ...

  2. C++知识点46——类继承中的类型转换与访问权限控制(中)

    接上一篇文章https://blog.csdn.net/Master_Cui/article/details/109741735 四.public继承.protected继承和private继承 子类 ...

  3. android 静态方法 构造方法,android基础-Java篇02:类和对象、构造方法、访问权限控制、重载、this关键字、static关键字...

    一.类和构造方法 (类和对象在百度百科已经有详细的介绍,这里只做简单的描述以及帮助理解:百度百科:类和对象,需要注意的是,百度百科类和对象的举例中都是C++,书写格式不要和Java混淆!) 什么是类? ...

  4. C# 类型运算符重载在类继承中的调用测试

    C# 类型运算符重载在类继承中的调用测试 这是一篇晦涩难懂的片面的研究 一,简单的继承层次 class CA {}class CB : CA{}class CC : CB{}}void Test(CA ...

  5. C++_类和对象_封装_访问权限_C++中struct和class的区别---C++语言工作笔记037

    然后我们再来看c++中的访问权限控制,其实这个跟java中的很像 可以看到有3个,public 是类内类外都可以访问 protected 是保护权限,在类内可以访问,但是在类外不行.  这个在子类的时 ...

  6. Java中的四种访问权限:public、protected、包访问、private

    所谓访问权限,指的就是本类中的成员变量.成员方法对其他类的可见性 试想一想,当我们修改一个非常庞大的项目时,如果所有变量和方法都是公共权限,那么后端中任何类都有权限去修改它的变量和方法,很有可能修改后 ...

  7. C++知识点11——this指针,const成员函数,访问权限控制

    1.this指针 每个类都有this指针,this指针指向this指针指向的是类的对象本身 class A { public:A() {}~A() {}void func() {cout<< ...

  8. private访问权限java_Java中的访问权限控制

    Java提供了public, private, protected 三个访问权限修饰词,提供了以下四种访问权限控制机制: 1.包访问权限: 2.Public访问权限: 3.Private访问权限: 4 ...

  9. 文件服务器共享文件夹访问权限,5对文件服务器中的共享文件夹进行访问权限控制...

    对文件服务器中的共享文件夹进行访问权限控制 1. 实训目的 在Windows Server 2003环境下设置文件服务器的目的是要对多用户进行资源共享,这其中经常遇到不同用户应该分配不同权限的问题,通 ...

最新文章

  1. 把java文件打包成.jar (jar命令详解)
  2. 半波整流后的灯泡功率是多少?
  3. 【274天】每日项目总结系列012(2017.11.06)
  4. ng机器学习视频笔记(二) ——梯度下降算法解释以及求解θ
  5. 1.21 方法的可变参数(String...names)
  6. boost::geometry::segment_view用法的测试程序
  7. 南京大学计算机科学与技术学费,南京大学计算机科学与技术系招生信息
  8. Linux系统学习: 进程、重定向和管道指令:xargs 指令的作用是
  9. ue4移动到一定距离_UE4移动组件详解(一)——移动框架与实现原理
  10. 如何使用终端下载 macOS Monterey 12.1 正式版
  11. python pdf转txt_Python之pdf转txt
  12. 2022五一杯数学建模
  13. CSDN超实用的浏览器插件—去自家网站搜索广告、超快捷万能搜索、各种实用小功能等诸多功能等你探索
  14. 音频(三)音色与spectrum 频谱图
  15. C++二进制文件读写,以及数据的拼合与还原
  16. 【AI视野·今日CV 计算机视觉论文速览 第187期 part1】Fri, 18 Dec 2020
  17. client-go实战之二:RESTClient
  18. 测试空间大数据软件(Hadoop + HBase + GeoWave + GeoServer)
  19. Dubbo Cloud Native 实践与思考 1
  20. 后疫情时代的酒旅业,让用户“安心”成为行业复苏唯一解?

热门文章

  1. 转://SIHA环境修改主机名实施步骤
  2. JS~字符串长度判断,超出进行自动截取(支持中文)
  3. Pyqt5 获取命令行参数sys.argv
  4. HashMap.values().addAll()异常
  5. NYOJ-199 无线网络覆盖
  6. 不藏私分享五個線上自學平台
  7. 使用Flink的Savepoint功能
  8. Commons IO
  9. 以太坊开发(二)使用Ganache CLI在私有链上搭建智能合约
  10. day 33(套接字,TCP 与 UDP)