当前位置: 首页 > news >正文

C++ 中的继承和多态

C++ 中的继承和多态

  • 一、继承
  • 二、函数重载、隐藏、覆盖、重写
    • 1.函数重载(Function Overload)
    • 2.函数隐藏(Function Hiding)
    • 3.函数重写与函数覆盖(Function Override)
  • 三、多态
  • 四、纯虚函数和抽象类
  • 五、多重继承的二义性(菱形继承)

在这里插入图片描述

一、继承

继承允许我们依据一个类来定义另一个类,这使得创建和维护一个应用程序变得更容易。这样做也达到了重用代码功能和提高执行效率的效果。

派生类的成员可以直接访问基类的保护成员(protected),但不能直接访问基类的私有成员(private)

继承分为公有继承、保护继承与私有继承,除了公有继承,剩下两个很少用到,三者区别如下:

在这里插入图片描述


二、函数重载、隐藏、覆盖、重写

1.函数重载(Function Overload)

C++规定在同一作用域中函数名相同但函数特征标(即参数个数、类型、顺序)不同时,构成函数重载

函数重载的注意事项:

  1. 返回值类型不能作为重载的标准。
  2. 参数是否为引用不能作为重载的标准,尽管某些时候能通过编译,但在调用时会产生二义性。
  3. 成员函数是否被static修饰也不能作为重载的标准,因为在通过实例化后的对象调用方法时无法区分是否要调用静态成员函数。
  4. 一个函数不能既作为重载函数,又作为有默认参数的函数,因为当调用函数时如果少写一个参数,系统无法判定是利用重载函数还是利用默认参数的函数,即 int func(int a)int func(int a = 0) 是不能在同一作用域中同时存在的。

这里还要特别注意一下const修饰函数或函数参数时的情况:

class A {
public:/*** 不管形参有没有const修饰实参都不会被修改,二者在调用时没有区别,因此不能构成重载*/void func(int a);void func(const int a); // NO/*** 由底层const修饰的指针指向的实参不能被修改,二者在调用时存在区别,因此可以构成重载*/void func_bot_p(int *a);void func_bot_p(const int *a); // YES/*** 不管有没有顶层const修饰,该指针指向的内容都可以被修改,二者在调用时没有区别,因此不能构成重载*/void func_top_p(int *a);void func_top_p(int *const a); // NO/*** 在const修饰引用时实参不能被修改,二者在调用时存在区别,因此可以构成重载*/void func_ref(int &a);void func_ref(const int &a); // YES/*** 由const修饰的成员函数只能由const对象调用,二者在调用时存在区别,因此可以构成重载*/void func_ret(int a);void func_ret(int a) const; // YES
};

2.函数隐藏(Function Hiding)

不同作用域中定义的同名函数会构成函数隐藏(不要求函数返回值和函数参数类型相同)。

类成员函数会屏蔽全局函数派生类成员函数会屏蔽与其同名的基类成员函数(但如果该基类成员函数为虚函数,且函数返回值和特征标相同则构成函数重写)。

#include <iostream>using namespace std;void func() {cout << "global::func()" << endl;
}class A {
public:/*** 隐藏了外部的func*/void func() {cout << "A::func()" << endl;}void use_func() {func();::func(); // 使用全局函数时要加作用域}
};class B : public A {
public:/*** 隐藏了基类的func*/void func() {cout << "B::func()" << endl;}void use_func() {func();A::func(); // 使用基类函数时要加作用域}
};int main() {A a;B b;a.use_func();b.use_func();
}
atreus@MacBook-Pro % g++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
A::func()
global::func()
B::func()
A::func()
atreus@MacBook-Pro % 

3.函数重写与函数覆盖(Function Override)

派生类中与基类同返回值类型、同名和同特征标虚函数重定义,构成虚函数覆盖,也叫虚函数重写

需要注意的是,在默认情况下,如果重新定义了继承的方法,应确保与原来的原型完全相同,但如果返回类型是基类引用或指针,则可以修改为指向派生类的引用或指针,这种新出现的特性叫做返回类型协变(covariance of return type)。

#include <iostream>using namespace std;class A {
public:void func() {cout << "A::func()" << endl;}virtual void func_v() {cout << "A::func_v()" << endl;}
};class B : public A {
public:/* 函数隐藏 */void func() {cout << "B::func()" << endl;}/* 函数重载 */void func_v() override {cout << "B::func_v()" << endl;}
};int main() {A *a = new B;a->func();a->func_v();delete a;
}
atreus@MacBook-Pro % g++ main.cpp -o main -std=c++11 
atreus@MacBook-Pro % ./main
A::func()
B::func_v()
atreus@MacBook-Pro % 

三、多态

多态是指一个方法同时具有多种形态,具体形态取决于调用该方法的具体对象。从实现的角度可以将多态分为编译时多态(主要通过函数模板、函数重载和运算符重载实现)和运行时多态(主要通过虚函数和函数重写实现)。

对于运行时多态,其实现主要有三个前提:

  • 存在继承
  • 存在函数重写(覆盖)
  • 存在基类指针或者引用指向子类对象

运行时多态的实现要借助于动态绑定,动态绑定借助于虚函数实现,虚函数的限制如下:

  • 只有类的成员函数才能声明为虚函数。
  • 基类的析构函数可以是虚函数且通常声明为虚函数。
  • 构造函数不能为虚函数。
  • 内联函数不能是虚函数。
  • 静态成员函数不能是虚函数。

虚函数、虚函数表及虚函数实现多态的原理

其中,动态绑定是运行时绑定,通过地址实现,它是指基类的指针或引用有可能指向不同的派生类对象。对于非虚函数,执行时实际调用该函数的对象类型即为该指针或引用的静态类型。而对于虚函数,执行时实际调用该函数的对象类型为该指针或引用所指对象的实际类型


四、纯虚函数和抽象类

当类声明中包含纯虚函数(定义是末尾有 = 0 的虚函数)时,则不能创建该类的对象,这个类变为抽象类,C++中的抽象类类似于Java中的接口,抽象类必须至少包含一个纯虚函数

此外,对于抽象类还有以下注意事项:

  1. 抽象类只能用作其他类的基类,当然也可以作为另一个抽象类的基类
  2. 抽象类不能用来定义对象,不能实例化,也不能用作参数类型、函数返回类型或显式转换的类型
  3. 如果一个非抽象类从抽象类中派生,则其必须通过覆盖来实现所有的继承而来的抽象成员函数
#include <iostream>/* 抽象类 */
class Car {
public:virtual void showName() = 0; // 纯虚函数
};class Audi : public Car {
public:void showName() override { std::cout << "Audi" << std::endl; }
};class Volvo : public Car {
public:void showName() override { std::cout << "Volvo" << std::endl; }
};int main() {Audi audi;Volvo volvo;audi.showName(); // Audivolvo.showName(); // Volvoreturn 0;
}

五、多重继承的二义性(菱形继承)

菱形继承是指当类B和类C同时继承于基类A,类D同时继承于类B和类C,此时类A中的成员变量和成员函数继承到类D中就变成了两份,在D中调用A中的成员会导致二义性,同时一个变量分两份存储也存在内存空间浪费的问题。

在这里插入图片描述

通过虚基类虚继承机制,可以在多继承中只保留一份共同成员,从而解决了多继承导致的命名冲突数据冗余

在继承方式前面加上 virtual 关键字就是虚继承,如果不采用虚继承,在类D中使用类A中的m_a时则需要通过 B::m_aC::m_a 来指定具体使用哪个m_a。

#include <iostream>using namespace std;class A {
protected:int m_a = 0;
};class B : virtual public A {
protected:int m_b = 1;
};class C : virtual public A {
protected:int m_c = 2;
};class D : public B, public C {
protected:int m_d = 3;public:D() {cout << m_a << endl;cout << m_b << endl;cout << m_c << endl;cout << m_d << endl;}
};int main() {D d;return 0;
}
atreus@MacBook-Pro % g++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
0
1
2
3
atreus@MacBook-Pro % 

C++标准库中的iostream类就是一个虚继承的实际应用案例。iostream从istream和ostream直接继承而来,而istream和ostream又都继承自一个共同的名为base_ios的类,是典型的菱形继承。

在这里插入图片描述


参考:

https://cloud.tencent.com/developer/article/1177174
https://blog.csdn.net/weixin_39640298/article/details/88725073
http://c.biancheng.net/view/2280.html

在这里插入图片描述

相关文章:

C++ 中的继承和多态

C 中的继承和多态 一、继承二、函数重载、隐藏、覆盖、重写1.函数重载&#xff08;Function Overload&#xff09;2.函数隐藏&#xff08;Function Hiding&#xff09;3.函数重写与函数覆盖&#xff08;Function Override&#xff09; 三、多态四、纯虚函数和抽象类五、多重继承…...

NestedFormer:用于脑肿瘤分割的嵌套模态感知Transformer

文章目录 NestedFormer: Nested Modality-AwareTransformer for Brain Tumor Segmentation摘要方法Global Poolformer EncoderNested Modality-Aware Feature AggregationModality-Sensitive Gating 实验结果 NestedFormer: Nested Modality-AwareTransformer for Brain Tumor …...

【SQLServer】sqlserver数据库导入oracle

将sqlserver数据库导入到oracle 实用工具&#xff1a; SQL Server Management Studio 15.0.18424.0 SQL Server 管理对象 (SMO) 16.100.47021.07eef34a564af48c5b0cf0d617a65fd77f06c3eb1 Microsoft Analysis Services 客户端工具 15.0.19750.0 Microsoft 数据访问组件 (MDAC) …...

【5.20】四、性能测试—性能测试工具

目录 4.5 性能测试工具 4.5.1 LoadRunner 4.5.2 JMeter 4.5 性能测试工具 性能测试是软件测试中一个很重要的分支&#xff0c;人们为了提高性能测试的效率&#xff0c;开发出了很多性能测试工具。一款好的测试工具可以极大地提高测试效率&#xff0c;为发现软件缺陷提供重要…...

朗诵素材-《少年正是读书时》(两角色主持朗诵)

少年正是读书时 1、少年正是读书时 男&#xff1a;我们生活在/古老的土地上 男&#xff1a;我们拥有/共同的梦想 女&#xff1a;那朗朗的书声/那浓浓的墨香 女&#xff1a;都在告诉我们 合&#xff1a;少年正是&#xff0f;读书时 2、为何要读书 男&#xff1a;养心&am…...

凭借这个笔记,拿下8家大厂offer....

如何拿到多家大厂的offer&#xff0c;没有过硬的实力&#xff0c;就需要不断的学习。 我是如何拿到&#xff0c;阿里&#xff0c;腾讯&#xff0c;百度等八家大厂的offer的&#xff0c;今天我就给大家来分享我的秘密武器&#xff0c;阿里大神整理的包括&#xff0c;测试基础&am…...

介绍一下全链路压测平台的相关内容

随着互联网技术的不断发展&#xff0c;越来越多的企业开始依赖互联网来实现业务的发展和增长。而对于这些企业而言&#xff0c;如何保证他们的业务在高并发、高负载的情况下依然能够正常运行&#xff0c;是非常重要的一个问题。为了解决这个问题&#xff0c;企业可以使用全链路…...

对于无效的数据,该如何处理

一、无效数据的来源&#xff1a; 在进行数据管理时&#xff0c;无效数据是非常常见的问题。 无效数据可能来自于数据采集、输入错误、数据处理或存储错误等方面。 这些无效数据会对结果造成严重的影响&#xff0c;因此需要及时发现和处理。 二、处理无效数据&#xff1a; …...

港联证券:机器人行业有望迎来整体性机会 六氟磷酸锂翻倍上涨

表示&#xff0c;当前AI调整的时间空间已接近13年水位&#xff0c;且调整的促发因素有望缓和&#xff0c;后续可积极一些。一方面&#xff0c;13年三次调整时间在40日以内、幅度在15%以内。当前AI调整已持续1个月、幅度在10%以上&#xff0c;时空已接近历史。另一方面&#xff…...

css 伪类选择器 结构伪类

css 伪类选择器 结构伪类 常用的&#xff1a; :first-child 所有兄弟元素中的第一个 :last-child 所有兄弟元素中的最后一个 :nth-child(n) 所有兄弟元素中的第n个 :first-of-type 所有同类型兄弟元素中的第一个 :last-of-type 所有同类型兄弟元素中的最后一个 :nth-of-type(…...

常用的表格检测识别方法-表格区域检测方法(上)

常用的表格检测识别方法 表格检测识别一般分为三个子任务&#xff1a;表格区域检测、表格结构识别和表格内容识别。本章将围绕这三个表格识别子任务&#xff0c;从传统方法、深度学习方法等方面&#xff0c;综述该领域国内国外的发展历史和最新进展&#xff0c;并提供几个先进…...

【运维知识进阶篇】集群架构-Rewrite重定向

Rewrite主要实现url地址重写&#xff0c;以及重定向&#xff0c;就是把传入web的请求重定向到其他url的过程。 分以下几种场景使用 1、地址跳转&#xff0c;用户访问一个URL&#xff0c;将其定向到另一个URL 2、协议跳转&#xff0c;用户通过http协议请求网站时&#xff0c;…...

JavaScript如何使用while循环

JavaScript 中的 while 循环是一种常用的循环结构&#xff0c;用于在满足一定条件时重复执行一段代码块。while 循环会先检查条件是否为真&#xff0c;如果为真&#xff0c;则执行循环体中的代码&#xff0c;然后再次检查条件。当条件变为假时&#xff0c;循环会结束。 while(…...

『MySQL 实战 45 讲』16 - “order by” 是怎么工作的

“order by” 是怎么工作的 首先创建一个表 CREATE TABLE t ( id int(11) NOT NULL, city varchar(16) NOT NULL, name varchar(16) NOT NULL, age int(11) NOT NULL, addr varchar(128) DEFAULT NULL, PRIMARY KEY (id), KEY city (city) ) ENGINEInnoDB;全字段排序 在 cit…...

怎么给移动硬盘查错?移动硬盘查错能恢复数据吗

移动硬盘在长期使用或使用不当的情况下&#xff0c;可能会出现硬盘文件损坏或者出现坏道等问题&#xff0c;影响数据安全和文件操作。这时候&#xff0c;移动硬盘查错工具就派上用场了。它可以帮助用户发现移动硬盘中的问题&#xff0c;并且还可以对移动硬盘进行修复。 但是&a…...

javaIO流之缓冲流

目录 简介1、字节缓冲流1.1构造方法1.2缓冲流的高效1.3为什么字节缓冲流会这么快&#xff1f;1.4byte & 0xFF 2、字符缓冲流2.1构造方法2.2字符缓冲流特有方法 3、练习 简介 Java 的缓冲流是对字节流和字符流的一种封装&#xff0c;通过在内存中开辟缓冲区来提高 I/O 操作…...

定义制造业操作(定义 MES/MOM 系统)

制造业操作包含众多工厂级活动&#xff0c;涉及设备&#xff08;定义、使用、时间表和维护&#xff09;、材料&#xff08;识别、属性、位置和状态&#xff09;、人员&#xff08;资格、可用性和时间表&#xff09;&#xff0c;以及这些资源与包含其信息碎片的众多系统之间的互…...

人工智能专栏第二讲——人工智能的基础技术

目录 一、机器学习 二、深度学习 三、自然语言处理 四、计算机视觉 五、总结 在第一讲中,我们介绍了人工智能的概念和发展趋势&#...

注意!ChatGPT的Plus账号也会被封禁

文 / 高扬&#xff08;微信公众号&#xff1a;量子论&#xff09; 最近经常看到有人丢个截图&#xff0c;然后悲伤地说&#xff0c;ChatGPT账号被封了。 这不是账号被封&#xff0c;而是所用的代理节点被OpenAI封了&#xff0c;换个节点即可。 这个截图才是账号真正被封的提示&…...

理解:Public Key Cryptography的应用

Applications Encryption with public key, decryption with private key Confidentiality or secrecy Encryption with private key, decryption with public key Integrity/authentication 一些概念特征的明确&#xff1a; public key&#xff1a;所有人都知道&#xff08;公…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...