C++primer -继承与动态绑定

继承:

一个类可以被另一个类继承,被继承类称为基类,继承类称为派生类。派生类继承基类后拥有基类的公有和保护成员。继承是一种强联系。

形式:在类声明之后用冒号列出该类继承的基类 class A{}; class B{};class C: public A, public B{} // C继承A\B

在要继承的类前面可以加访问说明符,如:

  • public:表示继承来的成员维持原访问标识权限;
  • protect表示继承来的成员在派生类中都是protected的;
  • private表示继承来的成员在派生类中都是private的。

继承的是函数的调用权,而不是函数的内存。

基类的定义注意事项:
  • 根节点基类通常都应该定义一个虚析构函数,即使该函数不执行任何操作也应如此: class Quote{virtual ~Quote();} 原因:只有对于虚函数,基类指针绑定到派生类的情况下,会根据其动态类型决定使用哪个函数版本,此时对于一个基类指针delete会调用实际绑定对象的析构函数,也就是派生类的析构函数,但若析构函数不是虚函数,则会按其静态类型,即执行基类的析构函数,导致派生类的独有的成员未被析构而发生内存泄漏。有析构函数的类,即使是虚析构函数,也不会被合成移动操作。

  • 通常将基类希望派生类覆盖的成员函数,声明为虚函数,形式:在函数声明之前加virtual,示例: class Quote{virtual double net_price(size_t n) const { return n * price;};

  • protected访问说明符:基类希望派生类能访问该成员,但不希望对外提供访问时,应将该成员声明为protected的,例:class Quote{protected : price;};

派生类的定义:
  • 派生类应用类派生列表声明所继承的基类,形式如: class Bulk_Quote: public Quote{};

  • 一个类要被用作基类时必须已定义:派生类的声明不包含其派生列表;

    • 只能继承已经定义过的类,不能继承一个不完全类型:

extern class Test; 
class testcs : public Test{}; // 会报错,提示Test不能是一个不完全类型。
  • 派生类不能控制其基类的部分初始化,应使用基类的构造函数初始化派生类的基类部分:

    • 例:Bulk_Quote类的构造函数Bulk_Quote(const std::string& book, double p, std::size_t qty, double disc ): Quote(book, p), min_qty(qty), discount(disc){}

    • 除非特别指出否则派生类的基类部分会被默认初始化。

    • 派生类的构造函数可以不显式调用基类构造函数,此时调用的是基类的默认构造函数。

    • 派生类默认不继承基类的构造函数,若希望派生类继承,应使用using 基类名::基类名;显式声明继承

  • 派生类可以直接访问基类的公有和保护成员:double Bulk_Quote:: net_price(size_t cnt)const {if(cnt >= min_qty) return n * (1 - discount) * price; else return cnt * price;} // price 为基类的保护成员,可以被派生类直接访问;

  • 派生类到基类的转换:可以将派生类对象绑定到基类的指针或引用中,在使用到基类指针或引用时可以用派生类、派生类的引用、派生类的指针代替。(因为派生类具有包含基类成员的子对象,也有包含派生类专有成员的子对象,所以可以转换为基类,但转换后只能使用其基类部分)

  • 派生类的析构函数只负责销毁派生类自身分配的成员,基类和其成员都是自动销毁的(基类的析构函数是被自动调用的,所以若基类的析构是删除的,则派生类的析构也是删除的)。析构函数的调用顺序与构造函数相反。合成的析构函数体为空。

  • 一个类可以在是基类的同时,是另一个类的派生类:

class Base; 
class Derived: public Base{}; 
class D2: Derived: puclic Derived{};

其他:

  • 若一个派生类是公有的,则其基类的公有成员,也是其接口的一部分;

  • 大多类是单继承的,C++是允许多继承的;

虚函数(virtual function):

即在C++语言中,基类允许派生类覆盖的函数,与派生类不做改变直接继承的函数区分对待。通常对于基类希望派生类覆盖的函数,基类将其函数声明成虚函数;

形式:在声明前加virtual.

class bird{ virtual void fly();};

以上例子中:不同的鸟都会飞,但不同的鸟种类有不同的飞的形态,继承了该类的函数要么实现该函数要么也声明该函数为虚函数

动态绑定:

对于继承了基类的派生类,在用到基类的地方,都可以用派生类代替。但实际使用时,若派生类重写了基类的虚函数成员,那么当基类引用实际绑定到的是派生类,则调用的是派生类重写的成员;若使用时实际绑定的是基类,则调用的是基类的该成员(该条只对覆盖有用,基类指针或引用不能调用派生类独有的函数或成员): 如:Quote类表示书籍,Bulk_Quote类继承了Quote类,表示打折书籍,Bulk_Quote类重写了Quote类用于计价的net_price()成员函数:

void print_total(const Quote& q){
    cout << "the price of those books is" << net_price() << endl;
}
// 若传入的是Bulk_Quote则使用Bulk_Quote类重写的net_price()成员,按打折方式计价,
// 若实际传入的是Quote则使用Quote的net_price()成员,按原价方式计价;
使用基类的引用或指针时,编译器并不了解所绑定对象的真实类型:

静态类型:编译时已知的类型 动态类型:实际运行时才得到的类型 对一个使用基类引用作形参的函数来说:形参是静态类型,实参是动态类型。:

double print_total(ostream& os, Quote& item, size_t n){} 
// Quote&是静态类型 
print_total(cout , item); // item的类型是动态类型
继承与静态成员:

基类中有静态成员,派生类在该静态成员为protected/public的情况下可调用该静态成员,但静态成员的定义只能有一个,派生类不能重写基类的静态成员函数:

class  Base{
protected:
    static void statmem();
};
class Derived: public Base { void f(const Derived&);};
void Derived::f(Derived&){
    Base::statmem();// 基类可以访问基类的静态成员函数
    Derived::statmem();// 派生类可以访问基类的静态成员函数
    derived_obj.statmem(); // 派生类的对象也可访问基类的静态成员函数
    statmem(); // 通过this访问,即通过当前派生类对象访问基类的静态成员函数
}
final:

若不希望继承发生,可以使用final限制该类不能继承,形式为在类名后加final: class NoDerived final : public Base{}; (final限制的类可以继承别的类)。f

不存在基类向派生类指针或引用的隐式转换:
Quote qt;
Bulk_Quote& rbqt = qt; 
// 派生类的引用不能绑定到基类
Bulk_Quote* pbqt = &qt; 
// 派生类的指针不能指向基类
Bulk_Quote bqt;
Quote& rq = bqt;
Bulk_Quote& bqt2 = rq; 
// 错误,基类对象不能隐式转换为派生类,即使该基类对象绑定的是同一个派生类可以通过dynamic_cast或static_cast进行转换
Bulk_Quote& bqt2 = dynamic_cast<Bulk_Quote> rq;
在对象间不存在类型转换:
Bulk_Quote bulk;
Quote item(bulk); 
// 这里使用的是Quote的拷贝构造函数Quote(const Quote);若该函数不存在,则该操作不合法
Quote item = bulk; 
// 这里使用的是Quote拷贝赋值运算符,若该操作未定义且拷贝构造函数未定义,则该语句不合法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/560548.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SnapGene Mac激活版 分子生物学软件

SnapGene Mac是一款功能全面、操作便捷的综合性分子生物学软件&#xff0c;专为Mac用户打造。它集成了DNA序列编辑、分析、可视化和团队协作等多种功能&#xff0c;为科研人员提供了一个高效、可靠的分子生物学研究工具。 SnapGene Mac激活版下载 在SnapGene Mac中&#xff0c;…

【Hadoop大数据技术】——Sqoop数据迁移(学习笔记)

&#x1f4d6; 前言&#xff1a;在实际开发中&#xff0c;有时候需要将HDFS或Hive上的数据导出到传统关系型数据库中&#xff08;如MySQL、Oracle等&#xff09;&#xff0c;或者将传统关系型数据库中的数据导入到HDFS或Hive上&#xff0c;如果通过人工手动进行数据迁移的话&am…

美容预约小程序:简单三步,开启高效预约模式

在当今的数字化时代&#xff0c;一个小程序可以极大地提高美容院的效率和客户满意度。下面我们将详细说明如何通过以下步骤来搭建一个美容院预约小程序。 首先&#xff0c;你需要注册并登录到乔拓云网&#xff0c;这是 一个在线平台&#xff0c;可以帮助你快速创建并管理你的小…

Kafka集群搭建可视化指南

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Kafka集群搭建可视化指南 前言准备工作硬件要求环境准备 kafka集群的部署与配置3.1 单节点部署与多节点集群搭建单节点部署&#xff1a;多节点集群搭建&#xff1a; 3.2 Broker配置与优化3.3 Topic的创…

快速访问github

修改本地hosts文件 GitHub访问慢的原因在于域名解析&#xff0c;通过修改本地的hosts文件&#xff0c;将远程DNS解析改为本地DNS解析。 fang 步骤1&#xff1a;打开hosts文件&#xff08;没有就创建&#xff09; host所在位置&#xff1a; C:\Windows\System32\drivers\etc…

销售经理(多继承/虚基类)

根据下图类之间的继承关系&#xff0c;以及main和输出定义&#xff0c;定义Staff类、Saleman类、Manager类和SaleManager类。 Staff类包含的数据成员有编号&#xff08;num)&#xff0c;姓名&#xff08;name)&#xff0c;基本工资&#xff08;basicSale&#xff09;。Saleman类…

[lesson42]类型转换函数(下)

类型转换函数(下) 类型转换函数 C类中可以定义类型转换函数 类型转换函数用于将类对象转换成其他类型 语法规则&#xff1a; 类型转换函数 与转换构造函数具有同等的地位使得编译器有能力将对象转换为其他类型编译器能够隐式的使用类型转换函数 无法抑制隐式的类型转换函…

项目实践:贪吃蛇

引言 贪吃蛇作为一项经典的游戏&#xff0c;想必大家应该玩过。贪吃蛇所涉及的知识也不是很难&#xff0c;涉及到一些C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。这里我会介绍贪吃蛇的一些思路。以及源代码也会给大家放到文章末尾。 我们最终的…

二维码门楼牌管理应用平台建设:取保候审的智能化监管

文章目录 前言一、取保候审的传统监管困境二、二维码门楼牌管理应用平台的优势三、取保候审备案信息的智能化处理四、保障居民合法权益五、展望未来 前言 随着信息技术的飞速发展&#xff0c;二维码门楼牌管理应用平台已成为现代社区治理的重要工具。本文重点探讨如何借助该平…

Vue【路由】

1&#xff1a;什么是单页应用程序&#xff08;single page application&#xff09; 所有得功能在一个html页面上实现 2&#xff1a;单页面应用程序的优缺点 优点&#xff1a;按需更新性能高&#xff0c;开发效率也高&#xff0c;用户的体验较好 缺点&#xff1a;学习成本高…

卷王问卷考试系统/SurveyKing调查系统源码

SurveyKing是一个功能强大的开源调查问卷和考试系统&#xff0c;它能够快速部署并适用于各个行业。 这个系统提供了在线表单设计、数据收集、统计和分析等功能&#xff0c;支持20多种题型&#xff0c;提供多种创建问卷的方式和设置。 项 目 地 址 &#xff1a; runruncode.c…

JavaFX--基础简介(1)

一、介绍 中文官网&#xff1a;JavaFX中文官方网站OpenJFX 是一个开源项目,用于桌面、移动端和嵌入式系统的下一代客户端应用程序平台。openjfx.cn是OpenJFX(JavaFX)的标准中文翻译网站&#xff0c;致力于方便开发者阅读官方文档和教程。https://openjfx.cn/ JavaFX 是一个开…

2024第八届图像、信号处理和通信国际会议 (ICISPC 2024)即将召开!

2024第八届图像、信号处理和通信国际会议 &#xff08;ICISPC 2024&#xff09;将于2024年7月19-21日在日本福冈举行。启迪思维&#xff0c;引领未来&#xff0c;ICISPC 2024的召开&#xff0c;旨在全球专家学者共襄盛举&#xff0c;聚焦图像信号&#xff0c;在图像中寻找美&am…

袁庭新ES系列15节|Elasticsearch客户端基础操作

前言 上一章节我们介绍了搭建Elasticsearch集群相关的知识。那么又该如何来操作Elasticsearch集群呢&#xff1f;在ES官网中提供了各种语言的客户端&#xff0c;我们在项目开发过程中有多种Elasticsearch版本和连接客户端可以选择&#xff0c;那么他们有什么区别&#xff1f;这…

uniapp Android 插件开发教程

一、下载uniapp提供的SDK Android 离线SDK - 正式版 | uni小程序SDK 二、在uniapp创建一个项目 查看包名&#xff1a;发行--> 原生app 云打包 三、进入dcloud官网 开发者中心 进入 应用管理 --> 我的应用 --> 点击应用名称-->各平台信息-->新增 这里需要这…

【可视化大屏开发】19. 加餐-百度地图API实现导航加线路热力图

需求 Web端使用场景中会涉及到地图导航路线情况&#xff0c;并利用热力图显示路况信息。 实现效果如下&#xff1a; 输入起始地点&#xff0c;选择并开始导航 最终效果 思路步骤 利用百度地图API显示地图交通拥堵情况的热力图&#xff0c;需要按照以下步骤进行开发 步骤1&a…

面试被问懵了:手撕 Transformer

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 今年最大…

Vue入门篇:概念,快速入门,插值表达式,核心特性,基本Vue指令

目录 1.Vue是什么2.快速入门3.插值表达式{{}}1.作用:2.语法:3.插值表达式的注意点: 4.Vue响应式核心特性5.Vue指令 1.Vue是什么 Vue是一个流行的JavaScript框架&#xff0c;用于构建用户界面。它是一种用于构建单页面应用程序&#xff08;SPA&#xff09;的渐进式框架&#xff…

MySQL 列数据跨表拷贝,一句SQL快速将表A每条记录的某些字段拷贝到表B每条记录的某些字段(A、B表通过ID等字段对应)

文章目录 MySQL 列数据跨表拷贝&#xff0c;一句SQL快速将表A每条记录的某些字段拷贝到表B每条记录的某些字段&#xff08;A、B表通过ID等字段对应&#xff09;背景定义表填充测试数据跨表一 一对应拷贝列数据SQL参考资料 MySQL 列数据跨表拷贝&#xff0c;一句SQL快速将表A每条…

【C++】:函数重载,引用,内联函数,auto关键字,基于范围的for循环,nullptr关键字

目录 一&#xff0c;函数重载1.1 函数重载的定义1.1.1.形参的类型不同1.1.2参数的个数不同1.1.3.参数的顺序不同1.1.4.有一个是缺省参数构成重载。但是调用时存在歧义1.1.5.返回值不同&#xff0c;不构成重载。因为返回值可接收&#xff0c;可不接受&#xff0c;调用函数产生歧…
最新文章