C++ 面向对象(继承)

news2025/1/21 15:07:24

三、继承

3.1 继承的概念

基于一个已有的类 去重新定义一个新的类,这种方式我们叫做继承

关于继承的称呼

一个类B 继承来自 类 A 我们一般称呼

A类:父类 基类

B类: 子类 派生类

B继承自A A 派生了B

示例图的语法

class vehicle // 车类
{
	
}

class car:public vehicle
{
	
}

3.2 继承的意义

1、可以实现代码复用,减少重复代码的劳动量

2、继承是实现多态的必要条件

3、继承本身就是为了实现多态的,顺便实现了代码复用

3.3 继承的基本语法

3.3.1 使用方法

3.3.1.1 基本语法
class 子类名称:继承方式 父类名称
{
	子类新增的成员;
}

class B:public A
{
}
3.3.1.2 基类对象初始化

在子类的构造函数中,通常需要在初始化列表中显式调用基类的构造函数,以完成对基类成员的初始化。例如:

在继承时,需要在子类的构造函数的初始化表中

显性的调用父类的构造函数 来完成对父类成员的初始化格式

构造函数名(int val_1 , int val_2): class_A(val_1 , val_2);

3.3.1.3 派生类中调用基类

在派生类中可以通过以下方式调用基类的成员:

类外访问:
    对象名.基类名::变量;
    对象名.基类名::函数名(函数的实参表);


类内访问:
    基类名::变量;
    基类名::函数名(函数的实参表);

3.3.2 示例代码一(基本语法1)

#include <iostream>
#include <string>

using namespace std;

class person
{
private:

public:
    string name;
    int id;
    int height;

public:
    person(string name , int id , int height)
        :name(name) , id(id) , height(height)
    {
        cout << "父亲构造函数" << endl;
    }
};

class man : public person
{
private:
    string name;
public:
    man(string name , int  id ,int height)
        : person(name , id ,height)
    {

    }
    void show_data()
    {
        cout << person::name << " " << person::id << " " << this->height << endl ; 
    }
};



int main(int argc, char const *argv[])
{
    man m("张三" , 1 , 131);
    m.show_data();
    return 0;
}

示例代码1 运行结果如下:

3.3.3 示例代码二(基本语法2)

#include <iostream>
#include <string>

using namespace std;

class person
{
private:

public:
    string name;
    string sex;
    int age;

public : 
    person(string name ,int age ,string sex)
        :name(name), age(age) ,sex(sex)
    {
        cout << "父类有参构造" << endl;
    }
    person()
    {
        name = "未设置姓名";
        age = -1;
        sex = "沃尔玛塑料袋";
        cout << "父类无参构造" << endl;
    }
    ~person()
    {
        cout << "我是父类的析构" << endl ;
    }

};


class student:public person
{
private:

public:
    int id;

public:
    student(string name , string sex ,int age ,int id)
        :person(name , age , sex ) , id(id)
    {
        cout << "子类有参构造" << endl;
    }

    student()
    {
        name = "未设置姓名";
        age  = -1;
        sex  = "沃尔玛塑料袋";
        id   = -1 ;
        cout << "子类无参构造" << endl;
    }
    ~student()
    {
        cout <<"我是子类的析构" << endl ;
    }
public:
    void show_data()
    {
        cout << "姓名 " << name << endl;
        cout << "年龄 " << person::age << endl;
        cout << "性别 " << this->sex << endl;
        cout << "学号 " << this->id << endl;
    }
};



int main(int argc, char const *argv[])
{
    student s1 ;

    s1.name ="张三";
    s1.person::age = 10;
    s1.sex = "男";
    s1.id = 10;
    s1.show_data();
    
    return 0;
}

示例代码2 运行结果如下:

 

3.4 继承的方式

3.4.1 类中的访问控制权限

类内子类类外
public
protected×
private××

而在继承中 也有三种访问方式:publicprotectedprivate

  • 公共继承 public
  • 保护继承 protected
  • 私有继承 private

访问关系如下图:

image-20241010215659071

3.4.2 示例代码三(继承方式

#include <iostream>
#include <string>

using namespace std;

class person
{
private:
    string name;
private:
    int age;
protected:
    string sex;

public:
    person(string name ,int age ,string sex)
        :name(name) , age(age) , sex(sex)
    {
        cout << "父类有参构造" << endl;
    }
    person()
    {
        name = "未设置姓名";
        age = -1 ;
        sex = "沃尔玛塑料袋";
        cout << "父类无参构造" << endl;
    }
    ~person()
    {
            cout << "我是父类的析构" << endl;
    }
};

class student : private person
{
private:

public:
    int id;
public:
    student(string name ,string sex ,int age ,int id)
        :person(name ,age ,sex),id(id)
    {
        cout <<"子类有参构造" << endl;
    }
    student()
    {
        cout << "子类无参构造" << endl;
    }
    ~student()
    {
        cout<< "我是子类的析构" << endl;
    }
public:
    void show_data()
    {

    }

};

class son : private student
{
private:
  
public:
    son()
    {
        student::id = 10;
    }
    ~son()
    {

    }
};


int main(int argc, char const *argv[])
{
    son s;

    while (1)
    {
        /* code */
    }
    
    return 0;
}

示例代码3  运行结果如下:

3.5 继承的底层解释

实际开发中 一般继承都采用 pubilc 继承方式

如果不写继承方式,默认使用的都是 private 方式继承

1、子类中会继承父类中所有成员 ,包括私有成员,只不过在子类中不能直接访问父类私有成员需要父类提供公有的函数来访问父类的私有成员

2、当父子类中出现了同名的函数时,访问来也不会冲突,即使形参不同,也不构成重载关系 愿意是两个函数不在同一个空间内,如果想访问父类的成员 需要加 类名 :: 来修饰

类外访问:
    对象名.基类名::变量;
    对象名.基类名::函数名(函数的实参表);
类内访问:
    基类名::变量;
    对象名.基类名::函数名(函数的实参表);

 3.5.1 示例代码四(继承模型)

#include <iostream>
#include <string>

using namespace std;

class person
{
private:
    string name;    // 姓名
    string sex;     // 性别
    int age;        // 年龄

public:
    void set_name(string name)
    {
        this->name = name;
        cout << name << endl;
    }
};

class student:public person
{
private:    
public:
    //1、子类如何访问父类的私有成员
    void set_data(string name , string sex , int age )
    {
        person::set_name(name);
    }
    //2、当父类 和 子类 函数名冲突时 咋办
    void set_name(string name)
    {
        person::set_name(name);
    }

    ~student()
    {
        person();
    }
};


int main(int argc, char const *argv[])
{
    student s1;
    s1.set_name("张三");

    student s2;
    s2.set_data("王五","男",11);
    
    person p1;
    p1.set_name("李四");
    return 0;
}

示例代码4 运行结果如下:

 

##拓展 在继承中析构和构造的区别

 #构造

1、父类的构造函数不会被子类继承

2、需要在子类的构造函数的初始列表中,显性的调用父类函数的构造函数
    完成对父类中继承过来的成员初始化
    
3、如果没有在子类的构造函数初始化列表中调用父类中的构造函数 则使用无参构造
    如果父类没有无参构造 会报错
    
4、构造函数的调用顺序是
    先调用父类函数的构造函数
    再调用子类函数的构造函数

#析构

1、父类的析构函数不会被子类继承
    
2、不管是否显性调用父类的析构函数,父类的析构函数都会被调用
    完成对父类中继承过来的成员的善后工作
    
3、子类的析构函数中 无需调用父类的析构函数
    
4、析构函数的调用顺序是
    先调用子类函数的析构函数
    再调用父类函数的析构函数




前情回顾: ​​​​​​​

第一篇

C++ 面向对象(封装)-CSDN博客

第二篇

C++ 面向对象(构造 & 析构函数)-CSDN博客

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

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

相关文章

JAVA-IO模型的理解(BIO、NIO)

前言 &#xff08;本文是作者学习制作rpc框架时&#xff0c;一些自用的笔记&#xff0c;并不会完整详细的介绍某个模块&#xff0c;会写大概的流程及一些相关概念&#xff0c;供日后复习使用~&#xff09; IO模型 先理解基本的IO流程&#xff1a; 应用A把消息发送到 TCP发送缓…

【Spring】原型 Bean 被固定

问题描述 在定义 Bean 时&#xff0c;有时候我们会使用原型 Bean&#xff0c;例如定义如下&#xff1a; Service Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class ServiceImpl { }然后我们按照下面的方式去使用它&#xff1a; RestController public class Hello…

奉加微PHY6230兼容性:部分手机不兼容

从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…

Python脚本实现通过JLink烧录Hex文件

1 安装JLink驱动程序 驱动安装包下载路径&#xff1a;https://www.segger.com/downloads/jlink/ 选择对应的版本下载&#xff1a; 将下载的安装文件双击进行安装。 2 安装 pylink 包 pip install pylink3 查询 JLink 设备的 serial number 将JLink通过USB线插入电脑。 w…

【Qt】04-Lambda表达式

前言一、概念引入二、使用方法2.1 基本用法代码示例2.2 捕获外部变量2.3 参数列表 三、完整代码mywidget.cppsecondwidget.cppmywidget.hsecondwidget.h 总结 前言 一、概念引入 Lambda表达式&#xff08;Lambda Expressions&#xff09;是C11标准引入的一种匿名函数对象&…

[STM32 HAL库]串口中断编程思路

一、前言 最近在准备蓝桥杯比赛&#xff08;嵌入式赛道&#xff09;&#xff0c;研究了以下串口空闲中断DMA接收不定长的数据&#xff0c;感觉这个方法的接收效率很高&#xff0c;十分好用。方法配置都成功了&#xff0c;但是有一个点需要进行考虑&#xff0c;就是一般我们需要…

汇编与逆向(一)-汇编工具简介

RadASM是一款著名的WIN32汇编编辑器&#xff0c;支持MASM、TASM等多种汇编编译器&#xff0c;Windows界面&#xff0c;支持语法高亮&#xff0c;自带一个资源编辑器和一个调试器。 一、汇编IDE工具&#xff1a;RadASM RadASM有内置的语言包 下载地址&#xff1a;RadASM asse…

Langchain+FastApi+Vue前后端Ai对话(超详细)

一、引入 首先可以先看下作者的文章 FastApi相关文章&#xff1a;创建最简单FastApi的项目Vue相关文章&#xff1a;最简单的aixos二次封装Langchain相关文章&#xff1a;如何使用LangSmith跟踪deepseek模型 二、后端搭建 1 项目文件结构 routers&#xff1a;存放api接口se…

leetcode49-字母异位词分组

leetcode 49 思路 通过一个哈希表进行记录每个分组&#xff0c;遍历strs&#xff0c;然后对每个字符串item进行排序&#xff0c;比如&#xff1a;acb bac cab都会被排序为’abc’,然后以abc作为map的key&#xff0c;value就是存放所有匹配出来为key的值&#xff0c;最后把ma…

深度学习 DAY1:RNN 神经网络及其变体网络(LSTM、GRU)

实验介绍 RNN 网络是一种基础的多层反馈神经网络&#xff0c;该神经网络的节点定向连接成环&#xff0c;其内部状态可以展示动态时序行为。相比于前馈神经网络&#xff0c;该网络内部具有很强的记忆性&#xff0c;它可以利用它内部的记忆来处理任意时序的输入序列&#xff0c;…

跨境电商使用云手机用来做什么呢?

随着跨境电商的发展&#xff0c;越来越多的卖家开始尝试使用云手机来协助他们的业务&#xff0c;这是因为云手机具有许多优势。那么&#xff0c;具体来说&#xff0c;跨境电商使用云手机可以做哪些事情呢&#xff1f; &#xff08;一&#xff09;实现多账号登录和管理 跨境电商…

【Linux】gawk编辑器二

一、变量 gawk编程语言支持两种变量&#xff1a;内建变量和自定义变量。 1、内建变量 gawk使用内建变量来引用一些特殊的功能。 字段和记录分隔符变量 数据字段变量 此变量允许使用美元符号&#xff08;$&#xff09;和字段在记录中的位置值来引用对应的字段。要引用记录…

部署Metricbeat监测ES

官方参考文档 安装Metricbeat curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-7.17.27-linux-x86_64.tar.gztar xzvf metricbeat-7.17.27-linux-x86_64.tar.gz设置 Metricbeat连接到 Elasticsearch 进入metricbeat目录配置metricbeat.yml …

Linux--运维

Mysql主从同步 通过将MySQL的某一台主机&#xff08;master&#xff09;的数据复制到其他主机&#xff08;slaves&#xff09;上&#xff0c;并重新执行一遍来执行 复制过程中一台服务器充当主服务器&#xff0c;而其他一个或多个其他服务器充当从服务器 为什么要做主从复制 …

【odbc】odbc连接kerberos认证的 hive和spark thriftserver

hive odbc驱动&#xff0c;以下两种都可以 教程&#xff1a;使用 ODBC 和 PowerShell 查询 Apache HiveHive ODBC Connector 2.8.0 for Cloudera Enterprise spark thriftserver本质就是披着hiveserver的外壳的spark server 完成kerberos认证: &#xff08;1&#xff09;可以…

家政服务小程序,打造智慧家政新体验

春节即将来临&#xff0c;家政市场呈现出了火热的场景&#xff0c;大众对家政服务的需求持续增加。 近年来&#xff0c;家政市场开始倾向数字化、智能化&#xff0c;借助科学技术打造家政数字化平台&#xff0c;让大众在手机上就可以预约家政服务&#xff0c;减少传统家政市场…

SQL在线格式化 - 加菲工具

SQL在线格式化 - 加菲工具 打开网站 加菲工具 https://www.orcc.online 选择“SQL 在线格式化” 或者直接访问网址 https://www.orcc.online/tools/sql 输入sql&#xff0c;点击上方的格式化按钮即可 输入框得到格式化后的sql结果

WPF1-从最简单的xaml开始.md

1. 最简单的WPF应用 1.1. App.config1.2. App.xaml 和 App.xaml.cs1.3. MainWindow.xaml 和 MainWindow.xaml.cs 2. 正式开始分析 2.1. 声明即定义2.2. 命名空间 2.2.1. xaml的Property和Attribute2.2.2. xaml中命名空间2.2.3. partial关键字 学习WPF&#xff0c;肯定要先学…

cursor重构谷粒商城02——30分钟构建图书管理系统【cursor使用教程番外篇】

前言&#xff1a;这个系列将使用最前沿的cursor作为辅助编程工具&#xff0c;来快速开发一些基础的编程项目。目的是为了在真实项目中&#xff0c;帮助初级程序员快速进阶&#xff0c;以最快的速度&#xff0c;效率&#xff0c;快速进阶到中高阶程序员。 本项目将基于谷粒商城…

Linux探秘坊-------3.开发工具详解(1)

1 初识vim编辑器 创建第一个vim编辑的代码 1.新建文件 2.使用vim打开 3.打开默认是命令模式&#xff0c;写代码需要在屏幕上输出“i”字符 1.写完代码后要按Esc键退出到指令模式2.再按shift:wq即可保存并退出vim &#xff08;因为不支持鼠标&#xff0c;通常 使用键盘上的箭…