Linux 学习记录44(C++篇)

news2024/12/24 21:45:15

Linux 学习记录44(C++篇)

在这里插入图片描述

本文目录

  • Linux 学习记录44(C++篇)
  • 一、静态成员变量/函数
    • 1. 静态成员变量
    • 2. 静态成员函数
  • 二、继承
    • 1. 继承的作用
    • 2. 继承的格式
    • 3. 子类对父类中成员的继承
    • 4. 子类中存在和父类同名成员时
    • 5. 继承中特殊的成员函数
      • (1. 构造函数
      • (2. 析构函数
      • (3. 拷贝构造函数
      • (4. 拷贝赋值函数
      • (综合示例
    • 6. 多重继承
      • (1. 格式
      • (2. 注意事项
    • 7. 菱形继承(钻石继承)
      • (1. 虚继承(virtual)
  • 三、多态
    • 1. 函数重写(override)
      • (1. 虚函数(virtual)
  • 思维导图
  • 练习

@

一、静态成员变量/函数

1. 静态成员变量

static修饰的成员变量被称为静态成员变量

  1. 不依赖于类对象的,独立于类体存在的,编译阶段分配在静态区
  2. 静态成员变量不占用类的大小
  3. 所有类对象共用同一个静态成员,如果通过某个类对象修改过静态成员变量,其他类对象的静态成员变量也会被修改
  4. 即使没有实例化类对象,也可以使用类中的静态成员变量
  5. 类在的静态成员变量一般是public权限的
  6. 静态成员变量需要在全局处声明,声明时可以给初始值也可以不给,不给就是0
class test
{
private:
    string str;
public:
    /*定义类中的静态成员变量*/
    static int num;
};

/*声明类中的静态成员变量*/
int test::num=10;

int main()
{
    return 0;
}

2. 静态成员函数

static修饰的成员函数被称为静态成员函数

  1. 独立于类外,不占用类的大小
  2. 调用:直接使用类名调用使用类对象调用
  3. 静态成员函数不能使用非静态成员变量
  4. 静态成员函数和非静态成员函数同名时不构成函数重载
  5. 静态成员函数和非静态成员函数作用域不同
  6. 静态成员函数没有this指针
class test
{
private:
    string str;
public:
    /*定义类中的静态成员变量*/
    static int num;
    static void show(void)
    {
        cout << num << endl;
    }
};

/*声明类中的静态成员变量*/
int test::num=10;

int main()
{
    test::show();
    test buf1;
    test buf2;
    buf1.num=20;
    buf2.show();
    return 0;
}

输出:
在这里插入图片描述

二、继承

继承指基于已有的类创建处新类的过程 【基类/派生类】 【父类/子类】

1. 继承的作用

1. 能提高代码的复用性,[父类/基类]中原有的内容在[子类/派生类]中无需再定义
2. 继承是实现多台的前提

2. 继承的格式

例如:已有class A,创建 class B继承自A
class B:权限A -----> 创建一个B类,用特点的权限继承方式继承自A
A类可以称为 父类、基类
B类可以成为子类、派生类
class B:public A{} //B类公有继承A类
class B:private A{} //B类私有继承A类
class B:protected A{} //B类受保护的继承A类
父类中的访问权限public:private:protectedpublic:private:protectedpublic:private:protected
继承方式publicprivateprotected
子类中的访问权限public:不能访问:protectedpublic:private:不能访问public:private:不能访问

3. 子类对父类中成员的继承

1. 子类汇继承父类中的所有成员,包括私有成员
2. 类之间的继承关系,可以理解为是【包含关系】
3. 子类中从父类继承的成员,先存放,放在首地址,父类的指针/引用可以指向子类的对象
4. 父类的指针,只能访问父类的空间,子类的指针可以访问的空间包含父类继承的和子类拓展的

4. 子类中存在和父类同名成员时

1. 通过子类对象默认访问的是,子类的成员
2. 如果想要访问父类的成员,使用类名加上域标识符可以访问父类中的内容
3. 也可以通过父类的指针指向子类对象,再来访问

5. 继承中特殊的成员函数

构造函数、析构函数、拷贝构造函数、拷贝赋值函数 都不会被继承

(1. 构造函数

1. 父类中的构造函数不会被继承
2. 实例化子类对象时,先调用父类中的构造函数,再调用子类中的构造函数
3. 如果父类中只有有参构造,子类必须在构造函数的初始化列表中显性的调用父类的有参构造

(2. 析构函数

  1. 父类中的析构函数不会被子类继承
  2. 先析构子类,再析构父类
  3. 有指针成员的情况:如果父类中有指针成员,需要在父类的析构函数中手动释放堆区的空间;如果子类中有指针成员,需要在子类的析构函数中手动释放堆区的空间
  4. 父类的析构函数,不需要再子类中手动调用,系统会自动调用析构函数

(3. 拷贝构造函数

申请空间并初始化

  1. 父类的拷贝构造不会被继承
  2. 如果父类中有指针成员,需要显性写出父类的深拷贝函数;如果指针成员在子类中九显性写出子类的深拷贝函数
  3. 子类的拷贝构造需要显性调用父类的拷贝构造,直接传子类的对象

(4. 拷贝赋值函数

拷贝赋值函数也涉及到深浅拷贝问题

  1. 拷贝赋值函数也不会被继承
  2. 子类和父类有不同的拷贝赋值函数
  3. 如果父类中有指针成员,就显性写出父类的深拷贝赋值函数,如果子类中有指针成员,就显性写出子类的深拷贝赋值函数,如果显性写出了子类的深拷贝赋值,子类的拷贝赋值函数内一定要显性调用父类的拷贝赋值函数。

(综合示例

#include <iostream>
using namespace std;

class Person
{
private:
    int *age;
    string name;
public:
    //无参构造
    Person():age(new int){cout << "Per无参构造" << endl;}
    //有参构造
    Person(string name,int age):name(name),age(new int(age))
    {cout << "Per的有参构造" << endl;}
    //拷贝构造
    Person(Person &other):age(new int(*(other.age)))
    {
        //*(this->age) = *(other.age);
        this->name = other.name;
    }
    ~Person()
    {
        cout << "释放了堆区的空间" << age << endl;
        delete age;
        cout << "Person的析构函数" << endl;
    }
    void show()
    {
        cout << "Per中age" << *age << endl;
    }
    void show_()
    {
        cout << age << endl;
    }
    //Person的深拷贝赋值
    Person &operator=(const Person &other)
    {
        if(this!=&other)
        {
            this->name = other.name;
            *(this->age) = *(other.age);
        }
        return *this;
    }
};
//定义Stu类继承自Person
//类默认是私有继承,常用的继承方式是公有的
class Stu:public Person
{
public:
    int score;
public:
    Stu(){}
    //子类的有参构造,在初始化列表中显性的调用父类的有参构造
    Stu(string name,int age,int score):Person(name,age),score(score)
    {cout << "Stu的有参构造" << endl;}
//    void show()
//    {
//        //cout << name << endl;
//        //cout << "Person的name" << Person::name << endl;
//        //子类中不能访问父类继承下来的私有成员
//        //cout << "Person中的name" << name << endl;
//        //子类中可以访问从父类继承下来的受保护的成员
//        //cout << "Person中的age" << age << endl;
//    }
    ~Stu(){cout << "Stu的析构" << endl;}
    //Person(Person &other)
    Stu(Stu &other):Person(other)   //对于Person的拷贝构造,传子类的对象,父类的引用可以引用子类的对象
    {
        this->score = other.score;
        cout << "Stu的拷贝构造" << endl;
    }
    Stu &operator=(const Stu &other)
    {
        if(this!=&other)
        {
            //显性调用Person的拷贝赋值
            Person::operator=(other);
            cout << "Stu的拷贝赋值函数" << endl;
            this->score = other.score;
        }
        return *this;
    }
};

int main()
{
    Stu s;   //无参构造
    s.show_();
    Stu s1("zhangsan",20,100);  //有参构造
    cout << "s1" << "\t" ;
    s1.show();
    //拷贝构造
    //Stu s2 = s1;  //调用拷贝构造,需要开辟空间
    s = s1;
    cout << "s" << "\t" ;
    s.show();
//    cout << "s1的地址" << &s1 << endl;  //a0
//    s1.Person::show();
//    Person *p = &s1;
//    p->show();  //通过父类指针访问到的是父类中的show函数
//    cout << "s1中首成员的地址" << &s1.score << endl;
    return 0;
}

6. 多重继承

一个子类由多个父类继承而来

(1. 格式

class B:public A,private C
class 类名:继承权限1 类1,继承权限2 类2......
{
	子类拓展的内容
}

例:

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
using namespace std;

class test1
{
private:
    string str;
    int* num;
public:
protected:
};
class test2
{
private:
    string str;
    int* num;
public:
protected:
};
class test3
{
private:
    string str;
    int* num;
public:
protected:
};

/*定义stu类以公有权限多重继承自test*/
class stu : public test1,public test2,public test3
{
private:
    int score;
public:
};

int main()
{
    stu buf1;
    return 0;
}

(2. 注意事项

1. 如果多个基类(父类)中有同名成员,会发生歧义,通过类名加上域限定符访问指定的成员
2. 特殊的成员函数调用和使用的规律和普通继承时一致
3. 多重继承时,构造函数的调用顺序,和继承的顺序有关,和初始化列表中的调用顺序无关

7. 菱形继承(钻石继承)

在这里插入图片描述

1. 公共基类的内容会在汇集子类中保留两份
2. 对于访问公共基类中成员时,会存在二义性的问题
3. 如果多次继承大型的公共基类,会导致子类的内存过大。

(1. 虚继承(virtual)

使用virtual关键字修饰的变量是虚继承

  1. 虚继承用于解决菱形继承存在的问题,通过菱形继承公共基类中的额内容只会在汇集子类中保存一份,不会造成子类的内存过大。
  2. 如果使用虚继承,对于公共基类的构造函数,需要直接使用基类名来调用(因为不知道通过那一条中间路径继承的基类)
  3. 虽然,只保留了一份公共基类,但是仍然可以通过指定路径来访问基类中的成员

例:

class Person //公共基类
{
public:
    string name;
    int age;
    Person(){cout << "p无参构造" << endl;}
    Person(string name,int age):name(name),age(age){}
};
//Stu虚继承Person
class Stu:virtual public Person
{
public:
    int score;
    Stu(){cout << "Stu无参构造" << endl;}
    Stu(int score):score(score){}
};
//B虚继承Person
class B:virtual public Person
{
    int bb;
public:
    B(){}
    B(int b):bb(b){}
};
class A:public B,public Stu//汇集子类
{
    int high;
public:
    A(){cout << "A无参构造" << endl;}
    A(int h,int s,int b,int a,string name):high(h),Stu(s),B(b),Person(name,a)
    {
    }
};
int main()
{
    //A a1;  //Person的构造函数先被调用
    A a1(100,78,9,18,"zhangsan");
    cout << "a2****************************" << endl;
//    cout << a1.B::age << endl;   //指定访问从B路径继承下来的age
//    cout << a1.Stu::age << endl;   //指定访问从Stu路径继承下来的age
    cout << a1.age << endl;   //直接通过汇集子类来访问基类中的成员
    return 0;
}

三、多态

静态多态:也称为编译期间的多态,编译器在编译期间完成的
动态多态:即运行时的多态,在程序执行期间(非编译期)判断所引用对象的实际类型,根据其实际类型调用相应的方法

多态按字面的意思就是多种形态,相同的方法调用,但是有不同的实现方式。多态性可以简单地概括为“一个接口,多种方法,实现接口与实现的分离。

1. 函数重写(override)

函数重写发生在父子类之间,指的是,在子类中重写父类的函数

要求:
1. 函数名相同
2. 参数列表相同
3. 函数声明相同
4. 只有虚函数能进行重写

(1. 虚函数(virtual)

使用virtual修饰的函数就是虚函数

  1. 只要父类中某个函数被定义为了虚函数,后面所有继承自该类的该成员函数都是虚函数
  2. 虚函数可以在子类中对父类继承的虚函数进行重写,如果不重写使用的还是父类中的函数
  3. 体现出函数重写的条件(父类的指针指向子类的成员)

思维导图

在这里插入图片描述

练习

全局变量,int monster = 10000;定义英雄类hero,受保护的属性string name,int hp,int attck;公有的无参构造,有参构造,虚成员函数 void Atk(){blood-=0;},法师类继承自英雄类,私有属性 int ap_atk=50;重写虚成员函数void Atk(){blood-=(attck+ap_atk);};射手类继承自英雄类,私有属性 int ac_atk = 100;重写虚成员函数void Atk(){blood-=(attck+ac_atk);}实例化类对象,判断怪物何时被杀死。

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
using namespace std;

class hero
{
private:

public:
    /*无参构造*/
    hero(){}
    /*有参构造*/
    hero(string str,int num1,int num2):name(str),Hp(num1),attck(num2){}
    /**/
    virtual void Atk(int* blood)
    {
        *blood-=0;
    }
protected:
    string name;
    int Hp;
    int attck = 60;
};

class Master:public hero
{
private:
    int ap_atk=50;
public:
    /*无参构造*/
    Master(){}
    /*有参构造*/
    Master(int num1):ap_atk(num1){}
    /**/
    void Atk(int* blood)override
    {
        *blood-=(attck+ap_atk);
    }
protected:
};

class shooter:public hero
{
private:
    int ac_atk=100;
public:
    /*无参构造*/
    shooter(){}
    /*有参构造*/
    shooter(int num1):ac_atk(num1){}
    /**/
    void Atk(int* blood)override
    {
        *blood-=(attck+ac_atk);
    }
protected:
};

int monster = 10000;

int main()
{
    Master buf1;
    shooter buf2;

    int i = 0;
    for(i=0;monster>0;i++) {
        buf1.Atk(&monster);
        buf2.Atk(&monster);
    }
    cout << "经过" << i << "次" <<endl;
    return 0;
}

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

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

相关文章

OpenAI遭集体诉讼!窃取数百万用户信息?明星大模型变“数据小偷”!

“尽管制定了购买和使用个人信息的协议&#xff0c;但被告采取了不同的方法&#xff1a;窃取。”近日&#xff0c;一家律师事务所用一份长达157页的诉讼将OpenAI告到法庭&#xff0c;指控其在利润的驱使下&#xff0c;窃取大量个人信息来训练人工智能模型。 起诉书称&#xff0…

UE4 TCP通信 (UE作为客户端接收字节)

在上一篇(UE4 TCP通信)基础上,实现UE客户端接收服务端推送的字节数据并解析。 效果 (注意看左上角的打印信息) 步骤 1. 首先新建一个工程,然后创建一个Actor蓝图,这里命名为“BP_TCPConnect” 打开“BP_TCPConnect”,添加如下节点: (1)当服务端与客户端断开连接时…

SpringBoot+Vue+Element-ui实现简单登录注册功能

目录 1.前端 &#xff08;1&#xff09;登录和注册页面 HomeView.vue RegisterView.vue &#xff08;2&#xff09; main.js&#xff0c;作请求和响应拦截 2.后端 &#xff08;1&#xff09;mapper.xml &#xff08;2&#xff09;mapper接口 &#xff08;3&#xff0…

六本入选!首批“十四五”职业教育国家规划教材书目

近日&#xff0c;教育部办公厅公布了首批“十四五”职业教育国家规划教材书目&#xff0c;其中广东泰迪智能科技股份有限公司携手院校联合编写的6本教材入选该名单。 入选首批“十四五” 职业教育国家规划教材介绍 高职“十四五”职业教育国家规划教材 Python编程基础(第2版)…

平时成绩综合评价与总成绩预测模型

已排除非本人创作部分 摘要 针对问题一&#xff0c;我们首先对所有团队的数据做了正态性检验&#xff0c;共x次作业&#xff0c;每次作业成绩分布均可用正态分布描述。其次&#xff0c;我们对团队之间的成绩变化做了格兰杰因果检验&#xff0c;列出了成绩变化相关的一部分团队…

STL补充:STL中遵循的左闭右开原则/STL随机访问

文章目录 左闭右开原则示例&#xff1a;示例中erase的用法不能写成s.erase(s.begin()left)的原因 STL中支持随机访问的迭代器 左闭右开原则 在 C 中&#xff0c;容器&#xff08;如 vector&#xff0c;set&#xff0c;map 等&#xff09;的迭代器都遵循左闭右开的原则。 也就…

微服务- Eureka 注册

1. 首先从结构方面来说 单体架构&#xff1a;比较适合用于小型项目&#xff08;像一些学生管理系统&#xff09;&#xff0c;简单方便&#xff0c;高度耦合 分布式架构&#xff1a;松耦合&#xff0c;扩展性好&#xff0c;但架构复杂&#xff0c;难度大&#xff0c;适合大型互联…

CIO40---3个亿数字化供应链实战

2019年某天&#xff0c;我被总裁叫到办公室&#xff0c;我当是VP A&#xff1a;企业情况 一家A股上市 市值150亿&#xff0c;年销售50亿&#xff0c; 员工4000人&#xff0c;全国4个工厂 家庭企业&#xff0c;高管老人多 经销商模式&#xff0c;总代模式&#xff0c;工程…

unserialize3

看着这个源码长度&#xff0c;就觉着比较简单 本题就一个__wakeup方法需要绕过&#xff0c;但是不对哦没有提示也不知道该参数得多少呀 本来都要复制进编译器写了&#xff0c;发现源码闭合有点问题&#xff0c;可能是做了隐藏 解题步骤 实在找不到了&#xff0c;就尝试了一下fl…

81、基于STM32单片机的颜色识别 TCS3200 RGB 检测系统设计(程序+原理图+PCB源文件+参考论文+开题报告+任务书+设计资料+元器件清单等)

摘 要 随着现代工业生产向高速化、自动化方向的发展&#xff0c;色彩识别广泛应用于各种工业检测和自动控制领域&#xff0c;而生产过程中长期以来由人眼起主导作用的颜色识别工作将越来越多地被相应的颜色传感器所替代。如&#xff1a;各种物体表面颜色识别&#xff08;产品包…

什么是三极管推挽电路

这是一个三极管推挽电路&#xff0c;上面是一个NPN的三极管&#xff0c;下面是一个PNP的三极管。 当输入信号为VCC时&#xff0c;上面的三极管导通&#xff0c;下面的三极管截止&#xff0c;输出信号为VCC-0.7V&#xff0c;这个0.7V就是上面NPN三极管BE间的导通压降 当输入信号…

Spring Bean 作用域的定义

在 Spring 配置中&#xff0c;我们可以通过 scope 属性来定义 Spring Bean 的作用域&#xff0c;可以接受 5 个内建的值&#xff0c;分别代表 5 种作用域类型&#xff0c;下面给大家详细总结一下&#xff1a; 1、singleton&#xff0c;用来定义一个 Bean 为单例&#xff0c;也…

【MATLAB第50期】基于MATLAB的RELM-LOO多输入单输出回归分类预测算法与RELM及ELM进行对比

【MATLAB第50期】基于MATLAB的RELM-LOO多输入单输出回归&分类预测算法与RELM及ELM进行对比 引言 RELM-LOO即通过LOO计算效率方法对其RELM模型正则化C系数进行寻优。 对于进化算法寻优来说&#xff0c; 结果更稳定。 可参考以下文献&#xff1a; [1] Shao Z , Er M J , W…

小红书测评类产品种草文案怎么写?品牌方必看

小红书逐渐成为了越来越多年轻人购物和分享的主流平台。测评类产品的种草文案尤为重要&#xff0c;因为它可以帮助消费者更好地了解产品的性能、使用方法以及适用场景&#xff0c;从而为购物决策提供参考。这个时候将某个产品植入进去&#xff0c;就会更容易被用户所接受&#…

C++高级编程01

目录 1、双冒号作用域运算符 2、namespace命名空间 3、using声明以及using编译指令 using 声明 4、C对C语言的增强 4、const链接属性 5、const分配内存情况 6、尽量用const代替define 7、引用 1、双冒号作用域运算符 ::代表作用域 如果前面什么都不添加 代表全局作用…

K8S资源控制器管理

资源控制器 1 资源控制器1.1 控制基础1.1.1 控制原理1.1.2 控制对象 1.2 标签选择器1.2.1 标签基础1.2.2 标签选择器 1.3 副本控制器1.3.1 RC&RS1.3.2 Deploy基础1.3.3 Deploy进阶1.3.4 DaemonSet1.3.5 任务控制器 1.4 监视控制器1.4.1 metrics服务1.4.2 HPA实践 1 资源控制…

Git 推送教程

一般 add commit push即可。Git全流程&#xff1a; git init #初始化仓库 git add .文件名 #添加文件&#xff0c;添加全部文件可以直接写. git commit -m "信息" #提交到本地仓库 git remote add origin 远程仓库地址 #链接远程仓库&#xff0c;创建主分支 git p…

【每日一题】2. 两数相加

【每日一题】2. 两数相加 2. 两数相加题目描述解题思路 2. 两数相加 题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一…

MySQL的体系架构

文章目录 前言MySQL的Server层MySQL的存储引擎1&#xff09;InnoDB 存储引擎2&#xff09;MyISAM 存储引擎3&#xff09;Memory 存储引擎 前言 在学习一种事务之前&#xff0c;我们需要先了解事物的基本组成结构&#xff0c;清楚了事物的基本组成结构之后&#xff0c;我们才能…

QCC51XX---chain是什么?

QCC51XX---系统学习目录_嵌入式学习_force的博客-CSDN博客 高通的DSP对很多人来说还是比较难以理解与操作的,DSP里最基本的是要认识音频的处理链路,也就是平台中的chain。他是由多个模块(operator)连接起来的,连接的方法sink和earbud有些不同,这里会从6.x开始sink的chain…