C++继承深入解析

目录标题

    • 1. 继承的基本概念
      • 1.1 为什么使用继承
      • 1.2 继承的语法
    • 2. 继承的类型
      • 2.1 公共继承(Public Inheritance)
        • 公共继承的特性
        • 公共继承的语法
        • 公共继承的实际应用
      • 2.2 保护继承(Protected Inheritance)
        • 保护继承的特性
        • 保护继承的语法
        • 保护继承的实际应用
      • 2.3 私有继承(Private Inheritance)
        • 私有继承的特点:
        • 私有继承的语法:
        • 私有继承的使用场景:
    • 3. 继承中的成员访问规则
      • 3.1 访问控制
      • 3.2 派生类的访问权限
    • 4. 继承的构造和析构过程
      • 4.1 构造过程
      • 4.2 析构过程
    • 5. 派生类的特殊成员函数
      • 5.1 派生类的构造函数
      • 5.2 派生类的析构函数
    • 6. 继承中的多态
      • 6.1 虚函数
      • 6.2 纯虚函数和抽象类
    • 7. 继承中的问题
      • 7.1 钻石问题
    • 8. 实际例子
    • 9. 总结


继承是面向对象编程语言如C++的一个核心概念,它允许创建基于已存在类(称作基类或父类)的新类(称作派生类或子类),继承其属性和行为,同时还可以添加或修改功能。本文将详细介绍C++中的继承机制,包括基类和派生类的创建、继承类型和多态。

1. 继承的基本概念

1.1 为什么使用继承

继承可以:

  • 提高代码的重用性。
  • 建立类之间的层次关系。
  • 为基于共享接口的多态性提供支持。

1.2 继承的语法

在C++中,继承的语法如下:

class BaseClass {// 基类的成员
};class DerivedClass : public BaseClass {// 派生类的成员
};

在这里,DerivedClass继承了BaseClass的公共和保护成员。

2. 继承的类型

2.1 公共继承(Public Inheritance)

在C++中,公共继承是一种最常用的继承方式,它体现了"是一个"(“is-a”)的关系。当一个类以公共的方式继承另一个类时,基类的公共成员和保护成员在派生类中保持其原有的访问级别。

公共继承的特性
  • 基类的公共成员:在派生类中仍然是公共的,这意味着它们可以在任何可以访问派生类对象的地方被访问。
  • 基类的保护成员:在派生类中仍然是保护的,这意味着它们只能在派生类内部以及派生类的子类中被访问。
  • 基类的私有成员:在派生类中不可直接访问,即使通过公共接口也不行。私有成员被封装在基类中,派生类无法访问。
公共继承的语法
class BaseClass {
public:void publicFunction() {// 公共成员函数}protected:void protectedFunction() {// 保护成员函数}private:void privateFunction() {// 私有成员函数}
};class DerivedClass : public BaseClass {
public:void useBaseFunctions() {publicFunction(); // 可以访问,因为它是公共的protectedFunction(); // 可以访问,因为它是保护的// privateFunction(); // 错误!无法访问基类的私有成员}
};

在上面的例子中,DerivedClass以公共的方式继承了BaseClass。因此,BaseClasspublicFunctionDerivedClass中仍然是公共的,protectedFunction仍然是保护的,而privateFunction则无法在DerivedClass中访问。

公共继承的实际应用

公共继承常用于创建类的层次结构,其中派生类是基类的一种特殊类型。例如,我们可以有一个Shape基类,然后有CircleSquare等派生类,每个派生类都是一种特殊的形状。

class Shape {
public:virtual void draw() = 0; // 纯虚函数,使Shape成为抽象基类
};class Circle : public Shape {
public:void draw() override {// 实现绘制圆形的代码}
};class Square : public Shape {
public:void draw() override {// 实现绘制正方形的代码}
};

在这个例子中,CircleSquare都是Shape的子类,它们都继承了Shapedraw方法,并提供了自己的实现。这种设计允许我们编写处理Shape对象的代码,而不必关心具体的形状类型,从而实现多态性。

2.2 保护继承(Protected Inheritance)

在C++中,保护继承(Protected Inheritance)是一种继承方式,它介于公共继承和私有继承之间。当一个类以保护的方式继承另一个类时,基类的公共成员和保护成员在派生类中都变为保护成员,而基类的私有成员仍然不可访问。

保护继承的特性
  • 基类的公共成员:在派生类中变为保护的,这意味着它们只能在派生类内部以及派生类的子类中被访问。
  • 基类的保护成员:在派生类中仍然是保护的,这意味着它们只能在派生类内部以及派生类的子类中被访问。
  • 基类的私有成员:在派生类中不可直接访问,即使通过公共接口也不行。私有成员被封装在基类中,派生类无法访问。
保护继承的语法
class BaseClass {
public:void publicFunction() {// 公共成员函数}protected:void protectedFunction() {// 保护成员函数}private:void privateFunction() {// 私有成员函数}
};class DerivedClass : protected BaseClass {
public:void useBaseFunctions() {publicFunction(); // 可以访问,因为它是保护的protectedFunction(); // 可以访问,因为它是保护的// privateFunction(); // 错误!无法访问基类的私有成员}
};

在上面的例子中,DerivedClass以保护的方式继承了BaseClass。因此,BaseClasspublicFunctionDerivedClass中变成了保护的,protectedFunction仍然是保护的,而privateFunction则无法在DerivedClass中访问。

保护继承的实际应用

保护继承通常用于创建类的层次结构,其中派生类需要将基类的接口和实现细节作为自己的保护成员,以便在进一步的派生中使用。这种方式不对外暴露基类的公共接口,而是将其作为派生类的内部实现的一部分。

class Base {
public:void basePublicFunction() {// 基类的公共成员函数}protected:void baseProtectedFunction() {// 基类的保护成员函数}private:void basePrivateFunction() {// 基类的私有成员函数}
};class Derived : protected Base {
public:void derivedFunction() {basePublicFunction(); // 可以访问,因为它是保护的baseProtectedFunction(); // 可以访问,因为它是保护的// basePrivateFunction(); // 错误!无法访问基类的私有成员}
};class FurtherDerived : public Derived {
public:void furtherDerivedFunction() {basePublicFunction(); // 可以访问,因为它是保护的baseProtectedFunction(); // 可以访问,因为它是保护的// basePrivateFunction(); // 错误!无法访问基类的私有成员}
};

在这个例子中,Derived类以保护的方式继承了Base类,因此Base的公共成员在Derived中变成了保护的。FurtherDerived类以公共的方式继承了Derived类,因此它可以访问Derived中的保护成员,这些成员实际上是Base类的公共成员。

2.3 私有继承(Private Inheritance)

私有继承是面向对象编程中的一个特性,其中一个类(称为派生类)继承另一个类(称为基类),但基类的公共成员和保护成员都成为派生类的私有成员。私有继承意味着这些继承来的成员不可以通过派生类的对象被外界访问,只能在派生类内部使用。

私有继承的特点:
  • 基类的公共成员和保护成员:在派生类中变为私有成员。
  • 基类的私有成员:在派生类中仍然是不可访问的。
  • 外部访问:派生类的对象不能使用基类的成员,这些成员对于派生类外部是隐藏的。
私有继承的语法:
class Base {
public:void basePublicMethod() {}
protected:int baseProtectedAttribute;
private:int basePrivateAttribute;
};class Derived : private Base {// Base的公共成员和保护成员现在是Derived的私有成员。public:void derivedPublicMethod() {basePublicMethod(); // 正确:Base的公共成员在Derived中可以访问,但在Derived外不可访问。baseProtectedAttribute = 5; // 正确:Base的保护成员在Derived中可以访问。// basePrivateAttribute; // 错误:Base的私有成员在Derived中无法访问。}
};int main() {Derived d;// d.basePublicMethod(); // 错误:现在basePublicMethod()是d的私有成员。return 0;
}

在这个例子中,Derived类私有继承了Base类,所以Base类的公共和保护成员都成为Derived类的私有成员。从外部看,Derived类的对象不能使用它从Base类继承来的成员,因为它们对外界是不可见的,即使它们在Base类中是公共或保护的。

私有继承的使用场景:

私有继承通常用于实现细节的隐藏和复用,而不是为了表示"is-a"关系。当你希望使用一个类的实现,但不想继承其接口时,私有继承是合适的选择。这样,派生类不会暴露基类的接口,但可以利用基类的实现。

私有继承可以被看作是一种强化的组合关系,而不是传统的"is-a"继承关系。在某些情况下,组合可能是更合适的选择,因为它能够提供更清晰的设计和更强的封装。但当需要访问基类的保护成员或需要重写虚函数时,私有继承可能更为合适。

3. 继承中的成员访问规则

3.1 访问控制

  • 公共成员:在任何地方都可访问。
  • 保护成员:在基类本身、派生类及其友元中可访问。
  • 私有成员:仅在基类本身及其友元中可访问。

3.2 派生类的访问权限

  • 公共继承:基类的公共成员在派生类中仍是公共的,保护成员仍是保护的,私有成员不可访问。
  • 保护继承:基类的公共和保护成员在派生类中都变成保护的。
  • 私有继承:基类的公共和保护成员在派生类中都变成私有的。

4. 继承的构造和析构过程

4.1 构造过程

当创建派生类对象时,首先调用基类的构造函数,然后是派生类的构造函数。

4.2 析构过程

析构过程与构造相反,先调用派生类的析构函数,然后是基类的析构函数。

5. 派生类的特殊成员函数

5.1 派生类的构造函数

派生类的构造函数可以使用成员初始化列表来调用基类的构造函数。

class DerivedClass : public BaseClass {
public:DerivedClass(int value) : BaseClass(value) {// 派生类构造体内的代码}
};

5.2 派生类的析构函数

派生类的析构函数不需要特别调用基类的析构函数,这会自动发生。

6. 继承中的多态

6.1 虚函数

通过在基类中声明函数为virtual,派生类可以重写该函数,实现运行时多态。

6.2 纯虚函数和抽象类

一个包含纯虚函数的类是抽象类,不能实例化。派生类必须重写所有纯虚函数,才能创建其对象。

7. 继承中的问题

7.1 钻石问题

当两个派生类继承同一个基类,并且另一个类又继承这两个派生类时,会产生钻石问题,可以通过虚继承解决。

class BaseClass {};class DerivedClass1 : virtual public BaseClass {};
class DerivedClass2 : virtual public BaseClass {};class FinalClass : public DerivedClass1, public DerivedClass2 {};

8. 实际例子

#include <iostream>// 基类
class Animal {
public:virtual void speak() {std::cout << "Some animal sound" << std::endl;}virtual ~Animal() = default; // 确保派生类能调用正确的析构函数
};// 派生类
class Dog : public Animal {
public:void speak() override { // 重写基类函数std::cout << "Woof!" << std::endl;}
};int main() {Dog myDog;myDog.speak(); // 输出: Woof!return 0;
}

9. 总结

C++的继承是一个功能强大的机制,它不仅能够帮助程序员创建层次化的类结构,还能够实现代码复用和多态性。理解如何正确使用继承对于编写高效和可维护的C++程序至关重要。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R2S+ZeroTier+Trilium

软路由使用ZeroTier搭建远程笔记 软路由使用ZeroTier搭建远程笔记 环境部署 安装ZeroTier安装trilium 环境 软路由硬件&#xff1a;友善 Nanopo R2S软路由系统&#xff1a;OpenWrt&#xff0c;使用第三方固件nanopi-openwrt。内网穿透&#xff1a;ZeroTier。远程笔记&…

银河麒麟操作系统 v10 离线安装 Docker v20.10.9

1查看系统版本 [rootweb-0001 ~]# cat /etc/os-release NAME"Kylin Linux Advanced Server" VERSION"V10 (Tercel)" ID"kylin" VERSION_ID"V10" PRETTY_NAME"Kylin Linux Advanced Server V10 (Tercel)" ANSI_COLOR"…

pyqt动画效果放大与缩小

pyqt动画效果放大与缩小 QPropertyAnimation介绍放大与缩小效果代码 QPropertyAnimation介绍 QPropertyAnimation 是 PyQt中的一个类&#xff0c;它用于对 Qt 对象的属性进行动画处理。通过使用 QPropertyAnimation&#xff0c;你可以平滑地改变一个对象的属性值&#xff0c;例…

服务器2080ti驱动的卸载与安装

服务器2080ti驱动的卸载与安装 前言1、下载驱动2、驱动卸载与安装2.1 卸载原来驱动2.2 安装新驱动 3、查看安装情况 前言 安装transformers库&#xff0c;运行bert模型时出错&#xff0c;显示torch版本太低&#xff0c;要2.0以上的&#xff0c;所以更新显卡驱动&#xff0c;重…

基于vgg16和efficientnet卷积神经网络的天气识别系统(pytorch框架)全网首发【图像识别-天气分类】

一个能够从给定的环境图像中自动识别并分类天气&#xff08;如晴天、多云、雨天、雪天闪电等&#xff09;的系统。 技术栈&#xff1a; 深度学习框架&#xff1a;PyTorch基础模型&#xff1a;VGG16与EfficientNet任务类型&#xff1a;计算机视觉中的图像分类 模型选择 VGG16 …

1.基于python的单细胞数据预处理-归一化

目录 归一化的引入移位对数皮尔森近似残差两个归一化方法的总结 参考&#xff1a; [1] https://github.com/Starlitnightly/single_cell_tutorial [2] https://github.com/theislab/single-cell-best-practices 归一化的引入 在质量控制中&#xff0c;已经从数据集删除了低质…

【网络安全】一次sql注入问题的处理

目录 问题 10.60.100.194&#xff0c;修改之前 修改方案 问题解决 测试过程 问题思考与总结 问题 一次sql注入问题的筛查报告&#xff0c;主要是sql注入的问题资源-CSDN文库 doc-new\20-设计文档\34-Mesh设备管理\100-网络安全 10.60.100.194&#xff0c;修改之前 修改…

Multitouch for Mac:手势自定义,提升工作效率

Multitouch for Mac作为一款触控板手势增强软件&#xff0c;其核心功能在于手势的自定义和与Mac系统的深度整合。通过Multitouch&#xff0c;用户可以轻松设置各种手势&#xff0c;如三指轻点、四指左右滑动等&#xff0c;来执行常见的任务&#xff0c;如打开应用、切换窗口、滚…

ansible部署lamp架构

搭建参考&#xff1a;ansible批量运维管理-CSDN博客 定义ansible主机清单 [rootansible-server ~]# vim /etc/hosts 192.168.200.129 host01 192.168.200.130 host02 [rootansible-server ~]# vim /etc/ansible/hosts [webserver] host01 host02 在ansible端编写index.html…

rk3588 安卓13 暴露相机开关接口

以前不知道有个系统属性可以做&#xff0c;后面的代码我几乎都用系统属性来写&#xff0c;比写个额外的广播接口方便多了。 实现一个相机的开关接口给上层调用&#xff0c;也就是打开后&#xff0c;上层无法再调用相机&#xff0c;关闭后可以正常打开&#xff0c;无需重启&…

为什么Redis6.0引入了多线程

Redis 6.0引入了多线程&#xff0c;主要原因有以下几点&#xff1a; 提高网络I/O的吞吐量&#xff1a;多线程可以更有效地处理大量的并发连接和请求&#xff0c;特别是在多核心服务器上。通过使用多线程来处理读写网络套接字&#xff0c;Redis能够更充分地利用系统资源&#x…

AMQP实战

AMQP AMQP是Advanced Message Queuing Protocol的缩写&#xff0c;意为高级消息队列协议。它是一种应用层协议&#xff0c;用于在分布式系统中进行消息通信。AMQP提供了可靠、安全、高效的消息传递机制&#xff0c;可以支持大规模的消息传递场景。 AMQP的主要特点包括以下几点…

DRF渲染之异常处理

异常处理 【1 】引言 Django REST Framework 这个就是我们常常说的DRF APIView的dispatch方法&#xff1a; 当请求到达视图时&#xff0c;DRF 的 APIView 类会调用 dispatch 方法来处理请求。在 dispatch 方法中&#xff0c;有一个关键的步骤是处理异常。如果在视图类的方法…

加速vivado编译工程

系统环境&#xff1a;windows11IDE环境&#xff1a;vivado2023.2工程&#xff1a;vivado自带的example project&#xff08;wave_gen&#xff09; Vivado支持多线程&#xff0c;可进一步缩短编译时间&#xff0c;这需要通过如下的Tcl脚本进行设置。综合阶段&#xff0c;Vivado可…

东软集团:用软件、大模型、生态领航智能汽车软件新纪元

“ 这是一次里程碑式的重大升级。 ” 整理 | 云舒 编辑 | 小白 出品&#xff5c;极新 在“新时代 新汽车”2024北京车展上&#xff0c;法拉利、保时捷、宾利、奔驰、宝马、奥迪、路虎、本田、尼桑、铃木以及极氪、零跑、赛力斯、AION埃安等都是东软的伙伴&#xff0c;当然还…

读天才与算法:人脑与AI的数学思维笔记24_预测性文本生成器

1. 起源 1.1. 人类讲故事可能起源于“假如……”这种问答结构 1.2. 讲故事是人类做安全试验的一种方式 1.2.1. 如果你问一个人“假如……”&#xff0c;其实是在探索你的行为对他可能带来的影响 1.3. 最早出现的故事极有可能就源自我们对在周遭混乱的环境中寻找某种秩序的渴…

书生作业:XTuner

作业链接&#xff1a; https://github.com/InternLM/Tutorial/blob/camp2/xtuner/homework.md xtuner: https://github.com/InternLM/xtuner 环境配置 首先&#xff0c;按照xtuner的指令依次完成conda环境安装&#xff0c;以及xtuner库的安装。 然后&#xff0c;我们开始尝试…

activiti 工作流基本使用

Activiti 介绍 Activiti 是一个开源架构的工作流引擎&#xff0c;基于bpmn2.0 标准进行流程定义。其前身是JBPM&#xff0c;Activiti 通过嵌入到业务系统开发中进行使用。 官方是这样介绍 activiti的&#xff1a; Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎&…

java发送请求-二次开发-get请求json

这里有2个判断 如果param为空则对url发送请求 再继续判断有值时&#xff0c;接口参数时json还是namevalue格式 因为json是带{,所以可以先写为param包含{}, 反之就是请求格式是url&#xff1f;param 请求json要带参数&#xff0c;所以需要使用setEntity方法&#xff0c; 最…

泰迪智能科技携手新乡学院开展“泰迪智能双创工作室”共建交流会

为深化校企合作&#xff0c;实现应用型人才培养目标。5月8日&#xff0c;广东泰迪智能科技股份有限公司河南分公司市场总监张京瑞到访新乡学院数学与统计学院参观交流&#xff0c;数学与统计学院院长赵国喜、副院长皮磊、张秦&#xff0c;教研室主任许寿方、姚广出席本次交流会…