我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++深入探究继承的概念与使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++深入探究继承的概念与使用

1、概念及定义

1.1 概念

继承主要的工作就是-----共性抽取

具体地讲:

①继承机制是面向对象程序设计使代码可以复用的最重要的手段;

②允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样实现的类称为派生类/子类。基于实现该类的原有类称为基类/父类

③继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。(比如:animal—>dog---->kinds of dogs)

④继承是类层次设计的复用

1.2 定义

定义方式:class 派生类:继承方式 基类

继承方式可以是 public、protected、private三种,他们在继承基类时,所具有特性以及表现出的结果也有所不同,具体如下:

以public的方式继承基类

结论:

在public的继承方式下:

①父类中的成员变量的访问权限,到子类中不会发生改变

②父类中的私有访问权限的变量在子类中不可见(不能直接被访问)

问题:类在设计的时候,访问权限应该如何选择?

应该遵循以下3点原则:

以protected的方式继承基类

结论:

在protected的继承方式下:

①基类中public修饰的 成员在子类中访问权限为protected

②基类中protected修饰的成员在子类中的访问权限依旧是protected

③父类中的private访问权限的变量在子类中不可见(不能直接被访问)

以private的方式继承基类

结论:

在private的继承方式下:

①基类中public修饰的 成员在子类中访问权限为private

②基类中protected修饰的成员在子类中的访问权限为private

③父类中的private访问权限的变量在子类中不可见(不能直接被访问)

上面详细分析了每一种个情况,下面我们针对上面的结论进行汇总:

注意:

1、基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。

2、基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的

3、在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

2、class与struct的区别

主要有以下3点区别:

3、赋值兼容规则

前提:一定在public的继承方式下才满足

可以直接使用子类对象给父类对象赋值,反过来不行

这个很好理解,具体和可以通过两个方面理解:

①子类和父类的关系是is–a的关系,因此使用子类给父类赋值时可以的

②从对象模型来说。

对象模型可以简单理解为成员变量在内存中的布局情况;

可以使用基类的指针指向子类的对象,反过来不行

如果一定要指向,必须强转,不推荐,仅仅是能通过编译,但是在使用的时候可能会造成程序崩溃

分析如下:

可以使用基类的引用去引用子类对象,反过来不行

引用在底层本质上就是使用指针实现的,因此它和指针的理解思路是一致的,这里就不再赘述。

4、继承中的作用域问题

明确:派生类和基类隶属于不同的作用域

那么,现在有这样一种情况:

基类和派生类中出现了同名的成员变量或成员方法。这种情况要如何去理解呢? 首先,他一定不是函数重载,因为函数重载的前提必须是在同一作用域。 其实它就是我们本模块要介绍的----同名隐藏(重定义)问题

基类和派生类中出现同名的成员时,会有如下问题的存在:

那么,该如何解决呢?

只需要在访问的时候加上 基类名称和作用域限定符即可,这样做的目的是明确告诉编译器被调用成员所处的作用域

建议:一般情况下,在继承体系中最好不要定义同名的成员

5、派生类(子类)的默认成员函数

5.1 构造函数

主要取决于基类的情况,分为两大类进行讨论:

基类没有显式定义任何构造函数

子类可以提供构造函数,也可以不提供构造函数 是否提供根据子类中完成的功能或者具体情况决定

基类显式定义了构造函数

①基类的构造函数是无参或者全缺省的

子类可以提供构造函数,也可以不提供构造函数

是否提供根据子类中完成的功能或者具体情况决定

②基类的构造函数是非默认构造函数

子类必须要定义自己的构造函数

在子类构造函数初始化列表位置显式调用基类的构造函数(完成从基类中继承下来的成员的初始化工作)

基类和子类构造函数的调用先后顺序是怎样的?

把握一点:

创建那个类的对象,编译器就会调用这个类的构造函数

例如:创建子类对象,本质上调用的是子类的构造函数,但是在子类的构造函数的初始化列表处会调用基类的构造方法来初始化从基类继承下来的对象。然后再去执行子类构造函数的函数体。 因此,从结果上来看是基类对象的构造函数先执行完毕,子类构造函数后执行完毕。

5.2 拷贝构造函数

取决于基类的情况,主要分为两类:

基类的拷贝构造函数未定义

子类的拷贝构造函数可定义可不定义,根据子类的实际情况决定

基类的拷贝构造函数定义了

子类也需要定义拷贝构造函数,并且需要在子类的拷贝构造函数初始化列表的位置显式调用基类的拷贝构造函数

5.3 赋值运算符重载

1.基类的赋值运算符重载未定义

子类可定义可不定义

2.基类的赋值运算符重载显式定义了

子类也需要定义,分为两个大的步骤:

①调用基类的赋值运算符重载给基类部分成员赋值base::operator= (d);

②给子类自己新增的部分进行赋值

注意:基类的operator= 与子类自己的 operator= 构成了同名隐藏,因此要加作用域限定符指定调用基类的operator=,否则默认调用子类自己的operator=,就会陷入无限递归

正确示范:

错误示范:

5.4 析构函数

编译器将子类的析构函数编译完成之后,会自动在子类析构函数的最后一条语句之后插入一条调用基类析构函数的汇编语句call ~Base();!

问题:基类和子类析构函数调用先后顺序?

6、基类中哪些成员被子类继承了

6.1 成员变量

普通成员变量,全部被继承!

这个我们在本文的1.2 定义这个模块已经全部验证!

静态成员变量也被继承了

注意:静态成员变量在整个继承体系中只有一份

验证:通过静态变量来记录创建对象的个数

class Base
{
public:
	Base(int a,int b)
	{
		_a = a;
		_b = b;
		++_count;
	}
	Base(const Base& b)
	{
		_a = b._a;
		_b = b._b;
		++_count;
	}
	Base& operator=(const Base& b)
	{
		_a = b._a;
		_b = b._b;
		return *this;
	}
	~Base()
	{
		cout << "Base::~Base()" << endl;
		--_count;
	}
public:
	int _a;
	int _b;
	static int _count;
};
int Base::_count = 0;
class Derived : public Base
{
public:
	Derived()
		:Base(1,2)
	{
	}
	Derived(int a,int b,int c)
		:Base(a,b)
		, _c(c)
	{}
	Derived(const Derived& d)
		:Base(d)
	{
		_c = d._c;
	}
	Derived& operator=(const Derived& d)
	{
		Base::operator=(d);
		_c = d._c;
		return *this;
	}
	~Derived()
	{
		cout << "Derived::~Derived()" << endl;
	}
public:
	int _c;
};
void Test()
{
	cout << &Base::_count << endl;
	cout << &Derived::_count << endl;
}

6.2 成员方法

普通成员方法,被子类继承了。

前面的代码均有体现,这里不再验证~

静态成员方法—也被子类继承了

验证:

7、友元函数被继承了吗

明确:友元函数不是类的成员函数,他只是在一个类中进行声明,目的是打破类的封装性去访问原本外部不可访问的成员。

这个问题很好测试,我们只需要为子类提供一个友元函数去访问父类中的protected访问权限的成员变量。让一个子类继承自父类,然后测试在父类中声明的友元函数是否能够访问子类中的protected/private成员变量即可!

如果可以访问,那就说明 友元函数也会被继承下来。

如果不可以访问,那就说明友元函数不会被继承下来

直接上例子:

Test函数测试结果:

结论:友元函数不能被继承!

本篇文章到这里就结束了,感觉有所帮助的读友,可以转发分享给身边的朋友并留下你们的足迹!

下篇我们讲讲C++中一些不同的继承体系~,我们下篇再见!

到此这篇关于C++深入探究继承的概念与使用的文章就介绍到这了,更多相关C++继承内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++深入探究继承的概念与使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++数据结构继承的概念与菱形继承及虚拟继承和组合分析

这篇“C++数据结构继承的概念与菱形继承及虚拟继承和组合分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++数据结构继承
2023-06-29

成为 ASP 继承和多态的大师:深入探讨高级概念和最佳实践

在 ASP 中掌握继承和多态:高级概念和最佳实践
成为 ASP 继承和多态的大师:深入探讨高级概念和最佳实践
2024-03-04

C++继承的赋值转换与菱形虚拟继承深入详解

今天我要给大家介绍C++中更深入的内容了,C++继承的赋值转换与菱形虚拟继承。C++这门语言为了使代码不冗余,做了些什么操作呢?C++的继承就很好地实现了类层次的代码复用,今天我就要来和大家好好聊一聊它了
2022-11-13

深入探讨PHP无状态的概念与特点

PHP是一种被广泛应用于Web开发的服务器端脚本语言,它是一种无状态的编程语言。所谓无状态,指的是PHP脚本在执行时不会记住之前的状态或数据,每次请求都是独立的,这为实现高并发,快速响应的Web应用提供了便利。无状态的概念在传统的Web
深入探讨PHP无状态的概念与特点
2024-03-06

JavaScriptcookie与session的使用及区别深入探究

这篇文章主要介绍了Java中Cookie和Session详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下
2022-11-13

深入探究JavaScript中WeakMap的原理与用法

这篇文章主要对JavaScript中的WeakMap进行深入探究,包括它的原理、用法和注意事项等,文中的示例代码简洁易懂,需要的小伙伴可以参考一下
2023-05-20

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录