C++的三种继承方式详解以及区别
C++的三种继承方式详解以及区别
前言
我发现有时候概念性的东西,理解起来还是很难的,于是本文用简单的几个例子,来说明这三种不同的继承方式,他们之前的区别~
一、public继承
基类的
public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可直接访问。派生类中的成员函数可以直接访问基类中的
public和protected成员,但不能直接访问基类的private成员。通过派生类的对象访问从基类继承的成员,只能访问
public成员。
#include<iostream>
using namespace std;
class CFather
{
public:
int m_testA{0};
protected:
int m_testB{0};
private:
int m_testC{0};
};
class CSon: public CFather
{
void test()
{
m_testA = 1; // 编译正确 :public 继承后,在内部或者外部都可以访问public成员
m_testB = 1; // 编译正确 :public 继承后,在内部可以访问protected成员
m_testC = 1; // 编译错误 :无论哪种继承,都无法访问private成员
}
};
int main()
{
CSon _test;
_test.m_testA = 2; // 编译正确 :public 继承后,在内部或者外部都可以访问public成员
_test.m_testB = 2; // 编译错误 :public 继承后,在外部无法访问protected成员
_test.m_testC = 2; // 编译错误 :无论哪种继承,都无法访问private成员
system("pause");
return 0;
}
二、protected继承
- 基类的
public和protected成员都以private身份出现在派生类中,但基类的private成员不可直接``访问。 - 派生类中的成员函数可以直接访问基类中的
public和protected成员,但不能直接访问基类的private成员。 - 通过派生类的对象
不能直接访问从基类继承的任何成员。
#include<iostream>
using namespace std;
class CFather
{
public:
int m_testA{0};
protected:
int m_testB{0};
private:
int m_testC{0};
};
class CSon: protected CFather
{
void test()
{
m_testA = 1; // 编译正确 :protected 继承后,在内部可以访问public成员
m_testB = 1; // 编译正确 :protected 继承后,在内部可以访问protected成员
m_testC = 1; // 编译错误 :无论哪种继承,都无法访问private成员
}
};
int main()
{
CSon _test;
_test.m_testA = 2; // 编译错误 :protected 继承后,在外部无法访问public成员
_test.m_testB = 2; // 编译错误 :protected 继承后,在外部无法访问protected成员
_test.m_testC = 2; // 编译错误 :无论哪种继承,都无法访问private成员
system("pause");
return 0;
}
此时,可以这么理解为 派生类 通过 protected继承 基类 之后 ,基类 中的 public变成了protected,其他保持原样。
class CFather
{
protected:// proteced 继承之后public变成了 proteced
int m_testA{0};
protected:
int m_testB{0};
private:
int m_testC{0};
};
三、private继承
- 基类的
public和protected成员都以private身份出现在派生类中,但基类的private成员不可直接访问。 - 派生类中的成员函数可以
直接访问基类中的public和protected成员,但不能直接访问基类的private成员。 - 通过派生类的对象
不能直接访问从基类继承的任何成员。
#include<iostream>
using namespace std;
class CFather
{
public:
int m_testA{0};
protected:
int m_testB{0};
private:
int m_testC{0};
};
class CSon: private CFather
{
void test()
{
m_testA = 1; // 编译正确 :private 继承后,在内部可以访问public成员
m_testB = 1; // 编译正确 :private 继承后,在内部可以访问protected成员
m_testC = 1; // 编译错误 :无论哪种继承,都无法访问private成员
}
};
int main()
{
CSon _test;
_test.m_testA = 2; // 编译错误 :private 继承后,在外部无法访问public成员
_test.m_testB = 2; // 编译错误 :private 继承后,在外部无法访问protected成员
_test.m_testC = 2; // 编译错误 :无论哪种继承,都无法访问private成员
system("pause");
return 0;
}
此时,可以这么理解为 派生类 通过 private继承 基类 之后 ,基类 中的 public与protected变成了private,其他保持原样。
class CFather
{
private:// private 继承之后public变成了 private
int m_testA{0};
private:// private 继承之后protected变成了 private
int m_testB{0};
private:
int m_testC{0};
};
四、三者区别
public继承方式
- 基类中所有
public成员在派生类中为public属性; - 基类中所有
protected成员在派生类中为protected属性; - 基类中所有
private成员在派生类中不能使用。
- 基类中所有
protected继承方式
- 基类中的所有
public成员在派生类中为protected属性; - 基类中的所有
protected成员在派生类中为protected属性; - 基类中的所有
private成员在派生类中不能使用。
- 基类中的所有
private继承方式
- 基类中的所有
public成员在派生类中均为private属性; - 基类中的所有
protected成员在派生类中均为private属性; - 基类中的所有
private成员在派生类中不能使用。
- 基类中的所有
下表汇总了不同继承方式对不同属性的成员的影响结果
| 继承方式/基类成员 | public成员 | protected成员 | private成员 |
|---|---|---|---|
| public继承 | public | protected | 不可见 |
| protected继承 | protected | protected | 不可见 |
| private继承 | private | private | 不可见 |
五、总结
1.不管继承方式如何,基类中的 private 成员在派生类中始终不能使用(不能在派生类的成员函数中访问或调用)。
2.如果希望基类的成员能够被派生类继承并且毫无障碍地使用,那么这些成员只能声明为 public 或 protected;只有那些不希望在派生类中使用的成员才声明为 private。
3.如果希望基类的成员既不向外暴露(不能通过对象访问),还能在派生类中使用,那么只能声明为 protected。
4.基类成员在派生类中的访问权限不得高于继承方式中指定的权限。例如,当继承方式为 protected 时,那么基类成员在派生类中的访问权限最高也为 protected,高于 protected 的会降级为 protected,但低于 protected 不会升级。再如,当继承方式为 public 时,那么基类成员在派生类中的访问权限将保持不变。
后话
我们这里说的是基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。private 成员的这种特性,能够很好的对派生类隐藏基类的实现,以体现面向对象的封装性。由于 private 和 protected 继承方式会改变基类成员在派生类中的访问权限,导致继承关系复杂,所以实际开发中我们一般使用 public。
C++的三种继承方式详解以及区别的更多相关文章
- python selenium 三种等待方式详解[转]
python selenium 三种等待方式详解 引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...
- js的2种继承方式详解
js中继承可以分为两种:对象冒充和原型链方式 一.对象冒充包括三种:临时属性方式.call()及apply()方式1.临时属性方式 复制代码代码如下: function Person(name){ ...
- Python selenium 三种等待方式详解
1. 强制等待第一种也是最简单粗暴的一种办法就是强制等待sleep(xx),强制让闪电侠等xx时间,不管凹凸曼能不能跟上速度,还是已经提前到了,都必须等xx时间.看代码: # -*- coding: ...
- JavaScript五种继承方式详解
本文抄袭仅供学习http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html 一. 构造函数绑定 ...
- Python selenium 三种等待方式详解(必会)
很多人在群里问,这个下拉框定位不到.那个弹出框定位不到…各种定位不到,其实大多数情况下就是两种问题:1 有frame,2 没有加等待.殊不知,你的代码运行速度是什么量级的,而浏览器加载渲染速度又是什么 ...
- SQL-----数据库三种删除方式详解
第一种 使用delete 语句 特点: delete 属于数据库操纵语言DML,表示删除表中的数据, 删除过程是每次从表中删除一行,并把该行删除操作作为事务记录在日志中保存 可以配合事件(tran ...
- Selenium 三种等待方式详解
我们在做WEB自动化时,一般要等待页面元素加载完成后,才能执行操作,否则会报找不到元素的错误,这样就要求我们在有些场景下加等待时间. 我们平常用到的有三种等待方式: 强制等待 隐式等待 显示等待 一. ...
- Selenium:三种等待方式详解
我们在做WEB自动化时,一般要等待页面元素加载完成后,才能执行操作,否则会报找不到元素的错误,这样就要求我们在有些场景下加等待时间. 我们平常用到的有三种等待方式: 强制等待 隐式等待 显示等待 一. ...
- Spring事务Transaction配置的五种注入方式详解
Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...
随机推荐
- docker专题 从入门到放弃
1.docker是什么 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚 ...
- python django对数据表的增删改查操作
新增操作:方式1:book = BookInfo(title='西游记',price=99)book.save() 方式2:BookInfo.objects.create(title='西游记',pr ...
- @RequestMapping 注解?
该注解是用来映射一个URL到一个类或一个特定的方处理法上.
- 什么时候使用session?什么时候使用application?
application:程序全局变量对象,对每个用户每个页面都有效session:用户全局变量,对于该用户的所有操作过程都有效
- 数据库中的ACID
参考链接:什么是ACID 数据库中的锁机制
- nginx使用与配置
一.nginx操作命令 nginx常用命令: 验证配置是否正确: nginx -t 查看Nginx的版本号:nginx -V 启动Nginx:start nginx 重新加载nginx:nginx.e ...
- spring-boot-learning-MongoDB
NoSQL可以极大提高互联网系统的性能,但是它有一些致命的缺陷,其中最为严重的就是计算功能卡分有限,例如,在一个10 万数据量的List 中,我只需要满足特定条件的元素在Red is 中,使用集合或者 ...
- dll反编译(修改引用文件、修改代码)再生成dll
问题描述 我们在日常开发中经常会遇到,想要对dll文件做修改的操作,但苦于没有源代码,只能想想其他办法 解决问题 办法就是通过几个工具来反编译.正向编译.修改属性 反编译.正编译 参考https:// ...
- 行内元素的padding和margin是否有效
行内元素的纵向padding和margin都是不考虑的,这是css规范定义的.inline元素确实可以设置垂直方向的padding和margin值,但是inline元素的margin和padding的 ...
- js 中的submit 回调函数
1.submit.php <?php $arr = $_POST; $arr['msg']=1; //echo $_POST['uname']; echo json_encode($arr); ...