嵌入式养成计划-39----C++静态成员--继承--多继承

news2024/11/19 10:39:09

九十一、静态成员

  • 静态成员变量是属于类的变量,而不是属于类的对象的。
  • 它们在类的所有实例中是共享的。
  • 它们具有类范围的生命周期,因此与全局变量有一些相似之处。

在数据成员前+static ----->静态数据成员
在成员函数前+static ------>静态成员函数

静态数据成员 必须在类外初始化,如果不初始化(不建议),默认为0。
静态成员函数只能访问静态数据成员,不能访问非静态数据成员。

91.1 静态成员 的 生命周期

  • 静态成员变量的 初始化: 静态成员变量在程序启动时由编译器自动初始化为默认值,或者可以在类外部显式初始化。

  • 静态成员变量的 使用: 静态成员变量可以通过类名或类的对象来访问,它们在程序的整个生命周期内都是可用的。

  • 静态成员变量的 销毁: 静态成员变量的销毁发生在程序结束时,它们的析构函数不会被调用,因为它们没有与特定对象相关联
    它们的内存会在程序结束时被释放。

91.2 静态成员 格式:

class 类名
{
	static 数据类型 变量名; // 静态数据成员必须在类外初始化
	static 函数返回值类型 函数名(形参列表) //静态成员函数
	{函数体}
};
数据类型 类名::变量名 = 初始化;

91.3 银行账户实例

#include <iostream>
using namespace std;
//封装 银行账号 类
class BankAccount
{
private:
    double balance; //余额
    static double interest_rate; //利率  静态数据成员
public:
    //无参构造函数
    BankAccount() {}
    //有参构造函数
    BankAccount(double m):balance(m)
    {}
    //静态成员函数 获取当前利率
    static double getInterestRate()
    {
        return interest_rate;
        //balance = 100;  不能访问非静态数据成员
    }
    //静态成员函数 设置当前利率
    static void setInterestRate(double rate)
    {
        interest_rate = rate;
    }
    //静态成员函数 获取连本带利的余额
    static double getLastMoney(BankAccount &account)
    {
        return account.balance*(1+interest_rate);
    }
};
double BankAccount::interest_rate = 0.03; //静态数据成员必须在类外初始化
int main()
{
    cout << BankAccount::getInterestRate() << endl;
    BankAccount::setInterestRate(0.05);
    cout << BankAccount::getInterestRate() << endl;
    BankAccount account1(1000.0);
    cout << BankAccount::getLastMoney(account1) << endl;
    return 0;
}

九十二、继承

92.1 继承 的 目的

  1. 实现代码的重用性 (复用性)
  2. 可以建立父类和子类之间的联系
  3. 多态的实现,通过继承,可以实现子类对父类的重写

92.2 继承

  • 保持已有类的特性,在原来的基础上,增加新的特性而构造出新类的过程 称 继承 / 派生
  • 被继承者 称为 : 父类 / 基类
  • 继承者 称为 : 子类 / 派生类

92.3 格式

class 类名:继承方式 类名
{
    子类的拓展;
};
//继承方式:  public公共继承    protected保护继承  private私有继承
//一般都是以共有继承

92.4 继承方式

  • public
  • protected
  • private
父类中数据成员权限public–protected–privatepublic–protected–privatepublic–protected–private
继承方式publicprotectedprivate
子类中从父类继承
下来的成员访问权限
public–protected–不可访问protected–protected–不可访问private–private–不可访问
  • 子类不可以访问从父类继承下来的私有数据成员
  • 子类可以访问从父类继承下来的受保护数据成员
  • 子类可以访问从父类继承下来的公有数据成员

92.5 继承中的特殊成员函数

92.5.1 构造函数

  • 基类的构造函数会被继承到派生类中,
  • 先调用基类的构造函数,再调用派生类的构造函数。

92.5.2 析构函数

  • 父类的析构函数会被继承到子类中,
  • 先析构子类再析构父类。

92.5.3 拷贝构造函数

  • 父类的拷贝构造函数会被继承到子类中,

  • 在子类中需要调用父类的拷贝构造函数时,执行子类从父类继承下来的数据成员的初始化工作。

  • 如果有深拷贝问题,则需要在父类和子类各自完成深拷贝工作。

92.5.4 拷贝赋值函数

  • 父类的拷贝赋值函数会被继承到子类中,
  • 在子类中需要调用父类的拷贝赋值函数,执行子类从父类继承下来的数据成员的赋值工作。
  • 注意:调用父类的拷贝赋值函数时,需要加上类名和作用域限定符
  • 如果有深拷贝问题,则需要在父类和子类各自完成深拷贝工作。

示例 :

#include <iostream>
using namespace std;
// 封装 人 类  父类(基类)
class Person
{
private:
    string name;
protected:
    int age;
public:
    int h;
public:
    //无参构造
    Person(){ cout << "父类的无参构造" << endl;}
    //有参构造函数
    Person(string n, int a, int h) :name(n),age(a),h(h)
    {
        cout << "父类的有参构造" << endl;
    }
    //拷贝构造函数
                 // const Person &other = other
                 //赋值兼容规则
                 //1.子类对象可以赋值给父类的对象
                 //2.子类对象可以初始化父类的引用
                 //3.父类的指针可以指向子类对象地址
    Person(const Person &other):name(other.name),age(other.age),h(other.h)
    {
        cout << "父类的拷贝构造" << endl;
    }
    //拷贝赋值函数
    Person &operator=(const Person &other)
    {
        name = other.name;
        cout << "父类的拷贝赋值" << endl;
        return *this;
    }
    //析构函数
    ~Person()
    {
        cout << "父类的析构函数" << endl;
    }
    void show()
    {
       cout << "父类" << endl;
    }
};
//封装 学生类  共有继承 人 类
class Stu:public Person  //子类  、派生类
{
private:
    int id;
    int math;
public:
    Stu() {cout << "子类的无参构造函数" << endl;}
    Stu(string n, int a, int h,int i, int m):Person(n,a,h),id(i),math(m)
    {
        cout << "子类的有参构造函数" << endl;
    }
    //拷贝构造函数
    Stu(const Stu &other):Person(other),id(other.id),math(other.math)
                          //Person(other)
    {
        cout << "子类的拷贝构造函数" << endl;
    }
    Stu &operator=(const Stu &other)
    {
        cout << "子类的拷贝赋值函数" << endl;
        id = other.id;
        Person::operator=(other);
        return *this;
    }
    ~Stu()
    {
        cout << "子类的析构函数" << endl;
    }
    void show()
    {
        cout << "子类" << endl;
        //cout << name << endl;  子类不可以访问从父类继承下来的私有数据成员
        cout << age << endl;  //子类可以访问从父类继承下来的受保护数据成员
        cout << h << endl; //子类可以访问从父类继承下来的公有数据成员
    }
};
int main()
{
    Stu s1;
    Stu s2("zhangsan",18,190,1001,99);
    //s2.show();  //默认调用子类的show
    s2.Person::show();  //调用从父类继承下来的show
    Stu s3(s2); //先调用父类的拷贝构造函数,再调用子类的拷贝构造函数
    s1 = s2;//先调用父类的拷贝赋值函数,再调用子类的拷贝赋值函数
    return 0;
}

92.6 小结

  1. 父类的数据成员初始化必须在子类之前,先调用父类的构造函数,再调用子类的构造函数。
  2. 当父类和子类出现同名同类型的函数时,不是重载,也不是重复定义,是重写,原因:作用域不同。
    如果子类实例化一个对象,对象调用该函数,默认调用是子类的函数,
    如果想调用父类的函数,则需要加上类名和作用域限定符。

九十三、多继承

93.1 概念

  • 多继承 :即一个子类可以有多个父类,它继承了多个父类的特性。

93.2 格式

class 子类名:继承方式1 基类名1,继承方式2 基类名2,······,继承方式n 基类名n
{
    子类自己的内容;
};

小作业

  • 多继承代码实现沙发床
  • 沙发床继承于沙发和床

我写的

#include <iostream>
using namespace std;

class Bed{
    friend class Sofa_Bed;
private:
    int size;
public:
    //无参构造
    Bed() {cout << "床的无参构造" << endl;}
    //有参构造
    Bed(int size):size(size) {cout << "床的有参构造" << endl;}
    //拷贝构造
    Bed(const Bed &other):size(other.size) {cout << "床的拷贝构造" << endl;}
    //拷贝赋值
    Bed &operator=(const Bed &other){
        cout << "床的拷贝赋值" << endl;
        this->size = other.size;
        return *this;
    }
    //析构函数
    ~Bed() {cout << "床的析构函数" << endl;}
    //功能函数
    void func() {cout << "能躺" << endl;}
};

class Sofa
{
    friend class Sofa_Bed;
private:
    int high;
public:
    //无参构造
    Sofa() {cout << "沙发的无参构造" << endl;}
    //有参构造
    Sofa(int high):high(high) {cout << "沙发的有参构造" << endl;}
    //拷贝构造
    Sofa(const Sofa &other):high(other.high) {cout << "沙发的拷贝构造" << endl;}
    //拷贝赋值
    Sofa &operator=(const Sofa &other) {
        cout << "沙发的拷贝赋值函数" << endl;
        this->high = other.high;
        return *this;
    }
    //析构函数
    ~Sofa() {cout << "沙发的析构函数" << endl;}
    //功能函数
    void func() {cout << "能坐" << endl;}
};

class Sofa_Bed:protected Bed, protected Sofa
{
private:
    string color;
public:
    //无参构造
    Sofa_Bed() {cout << "沙发床的无参构造" << endl;}
    //有参构造
    Sofa_Bed(string color, int size, int high):Bed(size),Sofa(high),color(color) {cout << "沙发床的有参构造" << endl;}
    //拷贝构造
    Sofa_Bed(const Sofa_Bed &other):Bed(other),Sofa(other),color(other.color) {cout << "沙发床的拷贝构造" << endl;}
    //拷贝赋值
    Sofa_Bed &operator=(const Sofa_Bed &other){
        this->color = other.color;
        this->Bed::operator=(other);
        this->Sofa::operator=(other);
        cout << "沙发床的拷贝赋值" << endl;
        return *this;
    }
    //析构
    ~Sofa_Bed() {cout << "沙发床的析构函数" << endl;}
    //功能
    void func() {
        cout << "沙发床" << endl;
        this->Bed::func();
        this->Sofa::func();
    }
    void show_info(){
        cout << "大小 : " << this->Bed::size << endl;
        cout << "高度 : " << this->high << endl;
        cout << "颜色 : " << this->color << endl;
    }
};

int main()
{
    Sofa_Bed sb1;
    Sofa_Bed sb2("黑色", 256, 56);
    puts("");
    sb2.func();
    sb2.show_info();
    puts("");
    sb1 = Sofa_Bed("灰色", 128, 90);//调用的是拷贝赋值,将匿名对象的值拷贝赋值给sb2
    puts("");
    sb1.show_info();
    puts("");
    return 0;
}

在这里插入图片描述

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

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

相关文章

接口自动化测试 —— 工具、请求与响应

1.工具介绍 postman &#xff1a;很主流的API测试工具&#xff0c;也是工作里面使用最广泛的研发工具。 JMeter&#xff1a; ApiPost&#xff1a; 2.安装postman&#xff1a; 安装好直接打开&#xff0c;不用注册。 二、通信模式&#xff1a; 1、同步通信&#xff1a; …

【走方格的方案数】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 #include <iostream> using namespace std; int func(int m,int n) {if(m1||n1){return mn;}return func(m-1,n)func(m,n-1); } int main() {int m, n;while (cin >>m >>…

word行距怎么设置?专业排版,让文档更具吸引力!

Microsoft Word是最常用的文字处理工具之一&#xff0c;广泛用于学术写作、商务沟通和文档编辑。掌握Word的基本功能是高效使用它的关键。本文将介绍word行距怎么设置的3种方法&#xff0c;以确保您的文档格式清晰、易读&#xff0c;让您的文档更具吸引力&#xff01; 方法1&am…

C++ 命名空间-----namespace(超详细解析,小白必看系列)

目录 一、前言 &#x1f34e;什么是C 二、关键字 三、命名空间&#xff08;重点&#xff09; &#x1f350;C语言--命名冲突 &#x1f349;C--命名空间的定义 &#x1f353;C--命名空间的使用 四、C输入&输出 五、共勉 一、前言 既博主学过C语言后又一新的语言&a…

动手学强化学习第2章多臂老虎机

2.1简介 多臂老虎机问题可以被看作简化版的强化学习问题。但是其只有动作和奖励没有状态信息&#xff0c;算是简化版的强化学习问题。 2.2问题介绍 2.2.1问题定义 在多臂老虎机(MAB)问题中&#xff0c;有一个有K根拉杆的老虎机&#xff0c;拉动每一根拉杆都对应一个关于奖励…

简单使用 Hugo 博客

之前用过 hugo&#xff0c;本次来分享一波&#xff0c;确实简单好用&#xff0c;可以持续使用&#xff0c;尤其是喜欢 GO语言的同学 hugo Hugo是一个用 Go语言 编写的静态网站生成器&#xff0c;可以快速地生成高效、安全和易于管理的静态网站。Hugo具有速度快、可定制性强、…

Linux引导故障排除:从问题到解决方案的详细指南

1 BIOS初始化 通电->对硬件检测->初始化硬件时钟 2 磁盘引导及其修复 2.1 磁盘引导故障 磁盘主引导记录&#xff08;MBR&#xff09;是在0磁道1扇区位置&#xff0c;446字节。 MBR作用&#xff1a;记录grub2引导文件的位置 2.2 修复 步骤&#xff1a;1、光盘进…

Javascript笔记:Web页面中的事件处理

1 任务队列 2事件处理&#xff1a;⼀个只有宏任务的示例 3 Web⻚⾯中的事件处理 3.1 定时器与事件处理&#xff1a;一个实例 4 Web⻚⾯中的事件处理 5 事件在DOM中的传播 5.1 两个阶段

C++ (Chapter 1)

C (一) 1.C的命名空间 先来看一个C语言的例子: 下面这段代码是可以正常运行的. #include<stdio.h> int rand 0; int main() {printf("%d \n", rand);return 0; }但是,包含了一个头文件之后,甚至无法通过编译. #include<stdio.h> #include<stdli…

尘封已久的功能!iPhone 15带来了一项早该使用的电池功能

了解如何在iPhone 15上检查电池周期&#xff0c;在设备使用寿命的某个阶段将非常有用。只要简单地看一眼完成的循环次数&#xff0c;你就可以确定你的电池有多健康&#xff0c;以及你是否需要很快更换它。 这是iPhone在过去一直缺失的东西。iPhone上有检查电池周期的数据&…

Altium Designer实用系列(三)----部分问题解决办法(连完所有的线之后还存在飞线,isolated copper...)

一、常见问题解决 1.1 连完所有的线之后还存在飞线 出现此问题可以尝试把该PCB先关闭&#xff0c;然后关闭Altium Designer软件。之后再打开Altium Designer&#xff0c;之后再进行DRC电气检查&#xff0c;可解决该问题。 1.2 isolated copper:split plane(xxx)on … 该问题…

计算机毕业设计选什么题目好?springboot智慧养老中心管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

C++入门篇1

文章目录 C入门篇11、命名空间1.1、命名空间定义1.2、命名空间的使用 2、输入&输出3、缺省参数3.1、缺省参数概念3.2、缺省参数分类 C入门篇1 1、命名空间 1.1、命名空间定义 命名空间是什么&#xff1f;是一种将相关功能和数据封装在一起的方式&#xff0c;以避免名称冲…

nginx如何安装 以及nginx的配置文件

Nginx 网站服务 是一个高性能 轻量级web服务软件&#xff0c; 高新能&#xff1a;对http并发连接的处理能很高&#xff0c;单台处理器可支持30000-50000个并发请求&#xff0c;&#xff08;一般设置在20000个左右&#xff09; 轻量级&#xff1a;nginx软件很小&#xff0c;安装…

c语言:通讯录管理系统(动态分配内存版)

前言&#xff1a;在大多数高校内&#xff0c;都是通过设计一个通讯录管理系统来作为c语言课程设计&#xff0c;通过一个具体的系统设计将我们学习过的结构体和函数等知识糅合起来&#xff0c;可以很好的锻炼学生的编程思维&#xff0c;本文旨在为通讯录管理系统的设计提供思路和…

GPU 基础知识整理

萌新&#xff1a; 在接触一款硬件时我会&#xff1a;基础硬件结构&#xff0c;线程结构&#xff0c;内存布局&#xff0c;数据吞吐量&#xff0c;等方面进行学习 首先GPU的特点: 并行性能&#xff1a;GPU 是专门设计用于并行计算的硬件&#xff0c;通常具有大量的处理单元&am…

Vue中的监视属性

一、监视属性的使用 &#xff08;一&#xff09;配置watch进行监视 当我们想要监视一个属性改变的时候就可以使用监视属性监视其变化并进行操作。 语法格式如下&#xff1a; watch:{ 监视属性名称 : { // 监视属性的配置项 } } 1. handler函数 当监视的属性发生变化时就调…

进程死锁的处理策略之预防死锁,避免死锁以及死锁的检测和解除

1.不允许死锁发生 1.静态策略&#xff1a;预防死锁 知识回顾:死锁的产生必须满足四个必要条件&#xff0c;只要其中一个或者几个条件不满足&#xff0c;死锁就不会发生。 1.破环互斥条件 互斥条件: 只有对必须互斥使用的资源的争抢才会导致死锁。 如果把只能互斥使用的资源…

数据结构和算法(12):词典

词典 逻辑上的词典&#xff0c;是由一组数据构成的集合&#xff0c;其中各元素都是由关键码和数据项合成的词条&#xff08;entry&#xff09;。 映射&#xff08;map&#xff09;结构与词典结构一样&#xff0c;也是词条的集合。 二者的差别仅仅在于&#xff0c;映射要求不同…

cpp文件操作

文件操作 数据流 在cpp中&#xff0c;流&#xff08;stream&#xff09;是一个抽象概念&#xff0c;用于描述如何从一个位置到又一个位置传输数据。流主要用于I/O操作。 数据流包括两大类&#xff1a;1. 输入流(istream)&#xff1a;数据从某个源流入程序, 2. 输出流(ostrea…