iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++深入探究继承的概念与使用
  • 349
分享到

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

2024-04-02 19:04:59 349人浏览 安东尼
摘要

目录1、概念及定义1.1 概念1.2 定义2、class与struct的区别3、赋值兼容规则4、继承中的作用域问题5、派生类(子类)的默认成员函数5.1 构造函数5.2 拷贝构造函数

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++继承内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++深入探究继承的概念与使用

本文链接: https://www.lsjlt.com/news/149674.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • C++深入探究继承的概念与使用
    目录1、概念及定义1.1 概念1.2 定义2、class与struct的区别3、赋值兼容规则4、继承中的作用域问题5、派生类(子类)的默认成员函数5.1 构造函数5.2 拷贝构造函数...
    99+
    2024-04-02
  • C++深入探究不同的继承体系
    目录单继承多继承菱形继承概念存在的问题解决方案菱形虚拟继承虚拟继承什么是虚拟继承内存层面理解虚拟继承虚拟继承和普通单继承的区别虚拟继承+菱形继承声明: 本文的测试环境为Windows...
    99+
    2024-04-02
  • 一文搞懂C++中继承的概念与使用
    目录前言继承概念及定义继承概念继承定义继承方式父类和子类对象赋值转换继承中的作用域派生类的默认成员函数派生类的友元与静态成员继承关系单继承多继承菱形继承前言 我们都知道面向对象语言的...
    99+
    2024-04-02
  • C++ 超详细梳理继承的概念与使用
    目录继承的概念及定义继承的概念继承定义定义格式继承关系和访问限定符继承基类成员访问方式的变化基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承与友元继承与静态成员复杂的菱...
    99+
    2024-04-02
  • C++深入探究引用的使用
    目录一. 引用的概念二. 引用特性三. 常引用四. 使用场景1. 做参数2. 做返回值3. 做返回值需要注意的问题五. 传值传引用效率对比1. 值和引用传参时的效率比较2. 值和引用...
    99+
    2024-04-02
  • C++中继承的概念和定义
    目录1.继承的概念及定义1.1继承的概念1.2继承的定义格式1.3继承基类成员访问方式的变化(1)公有继承(2)保护继承(3)私有继承1.4总结2.基类和派生类对象赋值转换3.继承中...
    99+
    2024-04-02
  • C++数据结构继承的概念与菱形继承及虚拟继承和组合
    目录继承的概念继承的定义基类和派生类对象之间的赋值转换继承中的作用域派生类的默认成员函数继承中的两个小细节继承和友元继承和静态成员单继承和多继承(菱形继承)虚拟继承概念虚拟继承的原理...
    99+
    2024-04-02
  • C++深入探究友元使用
    目录友元特点外部函数友元成员函数友元总结类友元友元 友元 friend 机制允许一个类授权其他的函数访问它的非公有成员. 友元声明以关键字 friend 开头 ,它只能出现在类的声明...
    99+
    2024-04-02
  • C++深入讲解类与封装的概念与使用
    目录一、类的组合二、类的封装三、类成员的作用域四、小结一、类的组合 电脑一般而言是由 CPU,内存,主板,键盘和硬盘等部件组合而成。 二、类的封装 类通常分为以下两个部分 类的实现...
    99+
    2024-04-02
  • C++数据结构继承的概念与菱形继承及虚拟继承和组合分析
    这篇“C++数据结构继承的概念与菱形继承及虚拟继承和组合分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++数据结构继承...
    99+
    2023-06-29
  • 成为 ASP 继承和多态的大师:深入探讨高级概念和最佳实践
    引言 在 ASP 中,继承和多态是面向对象编程 (OOP) 的关键概念,它们使您可以创建可重用的代码、组织代码并提高代码的可扩展性。掌握这些高级概念将使您能够创建更强大、更灵活的应用程序。 继承 继承允许一个类(子类)从另一个类(基类或父...
    99+
    2024-03-04
    ASP、继承、多态、封装、抽象类、接口
  • C++深入探究引用的本质与意义
    目录一、引用的意义二、特殊的引用三、引用是否占用存储空间四、引用的本质五、引用的注意事项六、小结一、引用的意义 引用作为变量别名而存在,因此在一些场合可以代替指针引用相对于指针来说具...
    99+
    2024-04-02
  • C++中的继承问题(继承基本概念、菱形虚拟继承的对象模型)
    目录一、继承的概念与定义格式概念及定义格式二、赋值兼容规则三、继承中的作用域四、子类的默认成员函数构造函数拷贝构造函数赋值运算符重载析构函数构造和析构函数调用顺序五、继承与友元、静态...
    99+
    2023-02-05
    C++的继承 继承基本概念 菱形虚拟继承
  • 深入探讨PHP无状态的概念与特点
    PHP是一种被广泛应用于Web开发的服务器端脚本语言,它是一种无状态的编程语言。所谓无状态,指的是PHP脚本在执行时不会记住之前的状态或数据,每次请求都是独立的,这为实现高并发,快速响...
    99+
    2024-03-06
    探讨 无状态 编程php php脚本
  • C++继承的赋值转换与菱形虚拟继承深入详解
    目录一、继承的概念及定义1.1、继承的概念1.2、继承的定义二、基类和派生类对象赋值转换三、继承中的作用域3.1、继承同名成员处理方式3.2、继承同名静态成员处理方式3.3、继承与友...
    99+
    2022-11-13
    C++继承的赋值转换 C++菱形虚拟继承
  • 深入探讨Golang中的泛型概念
    深入探索 Golang 中的泛型概念 前言 Golang 1.18 中引入的泛型是一种强大的语言特性,它允许您在代码中使用类型变量,从而提高代码的可重用性和可维护性。在这篇文章中,我们...
    99+
    2024-04-03
    golang 泛型 键值对
  • JavaScriptcookie与session的使用及区别深入探究
    目录1. cookie1.1 什么是cookie1.2 KOA中使用cookie1.3 expires和maxAge1.4 浏览器端设置和删除cookie2. session2.1 ...
    99+
    2022-11-13
    JavaScript cookie与session JavaScript cookie JavaScript session
  • C++深入探究二阶构造模式的原理与使用
    目录一、构造函数的回顾二、半成品对象三、二阶构造四、小结一、构造函数的回顾 关于构造函数 类的构造函数用于对象的初始化构造函数与类同名并且没有返回值构造函数在对象定义时自动被调用 问...
    99+
    2024-04-02
  • 详解C++中单继承与多继承的使用
    目录前言1.继承的概念和定义(1)继承的概念(2)继承的定义方法(2)继承后子类的成员类型2.基类与派生类的赋值转换(1)派生类赋值给基类(2)基类给派生类3.继承中的作用域(1)隐...
    99+
    2024-04-02
  • 探究Golang接口的核心概念与特性
    Golang是一门由谷歌开发的开源编程语言,其设计目标之一是简洁而高效。在Golang中,接口(interface)是一个非常重要的概念,它为实现抽象和多态性提供了一种机制。本文将深入...
    99+
    2024-03-06
    接口 golang 特性
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作