C++中运算符的重载以及静态成员和类的继承及多继承

运算符重载

赋值运算符重载

  • 种类:=、+=、-=、*=、/=、%=
  • 表达式:L # R (L:左操作数 #运算符 R:右操作数)
  • 左操作数:只能是左值
  • 右操作数:可以是左值,也可以是右值,在运算过程中不会被改变
  • 结果:自身的引用
  • 实现方式
1.成员函数实现:类名 & operator#(const 类名 &R){}2.全局函数实现:类名 &  operator#(类名 &L, const 类名 &R){}

自增、自减运算符重载

前置自增

  • 表达式:++0
  • 操作数:左值,运算过程中要被改变
  • 结果:自身的引用
  • 实现方式:
    成员函数实现:类名 & operator++()
    全局函数实现:类名 & operator++(类名 &O)

后置自增

  • 表达式:O++
  • 操作数:左值,运算过程中要被改变
  • 结果:右值(不可以被改变)
  • 实现方式:
    成员函数实现:const 类名 operator++(int)
    全局函数实现:const 类名 operator++(类名 &O,int)

代码示例


#include <iostream>using namespace std;//封装人  类
class Person
{
//    friend const Person operator+(const Person &L, const Person &R);friend Person & operator+=(Person &L, const Person &R);
private:int a;int b;
public://无参构造函数Person() {}//有参构造函数Person(int a, int b):a(a),b(b){}Person(const Person& p):a(p.a),b(p.b){}//成员函数实现 + 号运算符重载const Person operator+(const Person &R) const{Person temp;temp.a = a + R.a;temp.b = b + R.b;return temp;}//成员函数实现 >浩运算符重载bool operator>(const Person &R){if(a>R.a && b>R.b){return true;}else{return false;}}//成员函数实现+=运算符重载
//    Person & operator+=(const Person &R)
//    {
//        a += R.a; // a = a + R.a;
//        b += R.b;
//        return *this;
//    }//成员函数实现前++运算符重载Person & operator++(){++a;++b;return *this;}//成员函数实现后++运算符重载const Person operator++(int)  //区别前置自增{Person temp;temp.a = a++;temp.b = b++;return temp;}void display(){cout << "a = " << a << endl;cout << "b = " << b << endl;}
};全局函数实现+号运算符重载
//const Person operator+(const Person &L, const Person &R)
//{
//    Person temp;
//    temp.a = L.a + R.a;
//    temp.b = L.b + R.b;//    return temp;
//}//全局函数实现+=运算符重载
Person & operator+=(Person &L, const Person &R)
{L.a += R.a;L.b += R.b;return L;
}int main()
{Person p1(10,10);Person p2(10,10);//简化成://Person p3 = p1 + p2;  //本质: p3 = p1.operator+(p2)Person p3 = p1 + p2;  //本质: p3 = operator+(p1,p2)p3.display();//Person p4 = p1.operator+(p2);//p4.display();if(p3>p1){cout << "p3>p1" << endl;}cout << "=======================" << endl;Person p4(3,4);p4 += p1;p4.display();cout << "=======================" << endl;p1 = ++p4;p1.display();p4.display();cout << "=======================" << endl;Person p5(7,8);p2 = p5++;p2.display();p5.display();return 0;
}

插入提取运算符重载

  • 插入 << 提取 <<
  • cout是ostream类的对象
  • cin是istream类的对象

代码示例


#include <iostream>using namespace std;//封装人  类
class Person
{
//    friend const Person operator+(const Person &L, const Person &R);friend Person & operator+=(Person &L, const Person &R);friend ostream & operator<<(ostream &cout, const Person &p);friend istream & operator>>(istream &cin, Person &p);
private:int a;int b;
public://无参构造函数Person() {}//有参构造函数Person(int a, int b):a(a),b(b){}Person(const Person& p):a(p.a),b(p.b){}//成员函数实现 + 号运算符重载const Person operator+(const Person &R) const{Person temp;temp.a = a + R.a;temp.b = b + R.b;return temp;}//成员函数实现 >浩运算符重载bool operator>(const Person &R){if(a>R.a && b>R.b){return true;}else{return false;}}//成员函数实现+=运算符重载
//    Person & operator+=(const Person &R)
//    {
//        a += R.a; // a = a + R.a;
//        b += R.b;
//        return *this;
//    }//成员函数实现前++运算符重载Person & operator++(){++a;++b;return *this;}//成员函数实现后++运算符重载const Person operator++(int)  //区别前置自增{Person temp;temp.a = a++;temp.b = b++;return temp;}void display(){cout << "a = " << a << endl;cout << "b = " << b << endl;}
};全局函数实现+号运算符重载
//const Person operator+(const Person &L, const Person &R)
//{
//    Person temp;
//    temp.a = L.a + R.a;
//    temp.b = L.b + R.b;//    return temp;
//}//全局函数实现+=运算符重载
Person & operator+=(Person &L, const Person &R)
{L.a += R.a;L.b += R.b;return L;
}//全局函数实现插入运算符重载
ostream & operator<<(ostream &cout, const Person &p)
{cout << p.a << endl;cout << p.b << endl;return cout;
}//全局函数实现提取运算符重载
istream & operator>>(istream &cin, Person &p)
{cin >> p.a;cin >> p.b;return cin;
}int main()
{Person p1(10,10);Person p2(10,10);//简化成://Person p3 = p1 + p2;  //本质: p3 = p1.operator+(p2)Person p3 = p1 + p2;  //本质: p3 = operator+(p1,p2)p3.display();//Person p4 = p1.operator+(p2);//p4.display();if(p3>p1){cout << "p3>p1" << endl;}cout << "=======================" << endl;Person p4(3,4);p4 += p1;p4.display();cout << "=======================" << endl;p1 = ++p4;p1.display();p4.display();cout << "=======================" << endl;Person p5(7,8);p2 = p5++;p2.display();p5.display();cout << "=======================" << endl;// operator<<(cout,p2)cout << p2 << endl;  //本质   cout.perator<<(p2)//全局函数本质 operator<<(cout,p2)// ostream &   operator<<(ostream &cout,const Person &p)cout << "=======================" << endl;Person p6;cin >> p6;  //cin.operator>>(p2)// operator>>(cin,p6)// istream & operator>>(istream &cin, Person & p)cout << p6;return 0;
}

不能重载的运算符

  • 成员运算符 .
  • 成员指针运算符 ->
  • 作用域限定符 ::
  • 计算字节大小 sizeof()
  • 三目运算符 ?:

静态成员

概念

静态数据成员和静态成员函数是属于类的,不属于类的实例,它们在所有类的实例中是共享的

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

静态变量的初始化必须在类外初始化,如果没有初始化,默认为0
静态成员函数只能访问静态数据成员

格式

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

银行账户实例代码

#include <iostream>using namespace std;//封装银行账户 类
class BankAccount
{
private:double balance; //余额static double interest_rate; //利率  静态数据成员 属于类的public://无参构造BankAccount() {}//有参构造函数BankAccount(double b):balance(b){}//静态成员函数 获取当前的利率static double getInterestRate(){return interest_rate;}//静态成员函数,设置当前利率static void setInterestRate(double rate){interest_rate = rate;}//静态成员函数 获取连本带利的余额static double getLastMoney(BankAccount &account){return account.balance*(1+interest_rate);}
};double BankAccount::interest_rate = 0.05;  //在类外初始化 静态数据成员int main()
{cout << "当前利率:" << BankAccount::getInterestRate() << endl;BankAccount::setInterestRate(0.03);cout << "当前利率:" << BankAccount::getInterestRate() << endl;BankAccount account1(1000.0);BankAccount account2(2000.0);cout << "第一个人连本带利的余额:" << BankAccount::getLastMoney(account1) << endl;return 0;
}

类的继承

类的三大属性:封装、继承、多态

目的

  • 实现代码的重用性
  • 建立父类和子类之间的联系
  • 在实现多态的时候,通过继承,实现子类对父类函数的重写

概念

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

格式

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

代码示例

#include <iostream>using namespace std;//封装 人  类  父类/基类
class Person
{
private:string name;int age;
public://无参构造函数Person(){cout << "父类的无参构造函数" << endl;}//有参构造Person(string name, int age):name(name),age(age){cout << "父类的有参构造函数" << endl;}
};//封装 学生 类   共有继承人 类
class Stu:public Person   //子类 、派生类
{
private:int id;int math;
public://无参构造函数Stu(){cout << "子类的无参构造函数" << endl;}//有参构造函数Stu(string name, int age, int id, int math):Person(name,age),id(id),math(math){cout << "子类的有参构造函数" << endl;}};int main()
{Stu s("zhangsan",12,1001,78);return 0;
}

继承方式

父类中成员权限           public | protected | private         public | protected | private       public | protected | private
继承方式                        public                                 protected                             private
继承到子类中该成员的权限  public | protected | 不可访问        protected | protected | 不可访问    private | private  | 不可访问
类外是否可以访问子类      可以   | 不可以    | 不可以               不可以   | 不可以    | 不可以      不可以   | 不可以    | 不可以                                                                                
从父类中继承下来的成员

继承中的特殊成员函数

构造函数

父类的初始化必须赶在子类之前,换句话说,先调用父类的构造函数,再调用子类的构造函数

析构函数

析构函数的调用顺序:先调用子类的析构函数,再调用父类的析构函数
先构造的,后析构。后构造的,先析构

构造拷贝函数

父类的拷贝构造函数会继承到子类中,在子类的拷贝赋值函数中使用父类的拷贝赋值函数,来完成子类从父类继承下来的成员的赋值工作。
如果涉及深拷贝,则需要再子类和父类中各自完成深拷贝工作

代码示例

#include <iostream>using namespace std;//封装 人  类  父类/基类
class Person
{
private:string name;
protected:int age;
public:int h;
public://无参构造函数Person(){cout << "父类的无参构造函数" << endl;}//有参构造Person(string name, int age, int h):name(name),age(age),h(h){cout << "父类的有参构造函数" << endl;}//拷贝构造函数Person(const Person & other):name(other.name),age(other.age),h(other.h){cout << "父类的拷贝构造函数"  << endl;}//拷贝赋值函数Person & operator=(const Person &p){name = p.name;age = p.age;h = p.h;cout << "父类的拷贝赋值函数" << endl;return  *this;}void show(){cout << "父类的show" << endl;}
};//封装 学生 类   共有继承人 类
class Stu:public Person   //子类 、派生类
{
private:int id;int math;public://无参构造函数Stu(){cout << "子类的无参构造函数" << endl;}//有参构造函数Stu(string name, int age, int h, int id, int math):Person(name,age,h),id(id),math(math){cout << "子类的有参构造函数" << endl;}//拷贝构造函数Stu(const Stu & s):id(s.id),math(s.math),Person(s){cout << "子类的拷贝构造函数" << endl;}//拷贝赋值函数Stu & operator=(const Stu & s){Person::operator=(s);id = s.id;math = s.math;cout << "子类的拷贝赋值函数" << endl;return *this;}void show(){cout << "子类的show" << endl;cout << h << endl; //通过共有继承,类外、子类可以访问父类共有成员cout << age << endl; //通过共有继承,子类可以访问父类保护成员,类外不可以访问//cout << name << endl;//通过共有继承,子类不可访问父类私有成员,类外不可以访问}};int main()
{Stu s("zhangsan",12,190,1001,78);Stu s2=s;Stu s3;s3 = s2;//    s.show();
//    s.Person::show();return 0;
}

总结

  • 父类的初始化必须赶在子类之前,也就是先调用父类的构造函数,再调用子类的构造函数
  • 当父类的函数和子类的函数是同名类型时,不会报错,原因是因为作用域不同,如果子类实例化出一个对象,这个对象调用该函数,调用的是子类的函数,如果调用父类中函数,则需要加上类名和作用域限定符

多继承

概念

一个类由多个类公共派生

格式

class 类名:继承方式1 类名1,继承方式2 类名2,.....,继承方式n 类名n
{子类的拓展
};

代码示例

#include <iostream>using namespace std;//封装 沙发的类
class Sofa
{
private:string sitting;
public://无参构造Sofa() {cout << "沙发的无参构造" << endl;}//有参构造函数Sofa(string s):sitting(s){cout << "沙发的有参构造" << endl;}void display(){cout << sitting << endl;}
};//封装 床 类
class Bed
{
private:string sleep;public://无参Bed() {cout << "床的无参构造" << endl;}//有参Bed(string s):sleep(s){cout << "床的有参构造" << endl;}void display(){cout << sleep << endl;}
};//封装 沙发床类  继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:int w;
public://Sofa_Bed(){cout << "沙发床的无参构造" << endl;}//有参构造Sofa_Bed(string sit, string s, int w):Bed(s),Sofa(sit),w(w){cout << "沙发床的有参构造" << endl;}};int main()
{Sofa_Bed s;Sofa_Bed s1("可坐","可躺",123);s1.Sofa::display();s1.Bed::display();return 0;
}

总结

  • 子类由多个父类共同派生,子类调用构造函数的顺序是最后调用自己,对于多个父类的构造函数顺序的调用,和初始化列表的书写顺序无关,和继承时候的顺序有关
  • 当多个父类中有同名同类型的函数,子类对象调用该函数时,需表明属于哪个类,加上类名和作用域限定符

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

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

相关文章

远程Linux/ubuntu服务器后台不间断运行py文件/sh脚本

通常我们在生产环境中运行一些项目时需要将程序不间断的运行在服务器上&#xff0c;并且将日志文件打印到某个文件中&#xff0c;直到程序运行结束&#xff0c;下面介绍了在Linux服务器上不间断运行py文件的方式&#xff0c;以及如何保存相应的日志信息。 对于 .py 文件&#x…

SLAM十四讲学习笔记 第二期:部分课后实践代码

持续更新.... 前期准备第二讲实验一&#xff1a;简单输出 第五讲任务一&#xff1a;imageBasics&#xff08;Ubuntu配置opencv&#xff09;任务二&#xff1a;双目匹配点云&#xff08;Ubuntu配置pangolin&#xff09;检验部分我认为可以加深对CMake的理解 任务三&#xff1a;r…

pandas数据分析——groupby得到分组后的数据

groupbyagg分组聚合对数据字段进行合并拼接 Pandas怎样实现groupby聚合后字符串列的合并&#xff08;四十&#xff09; groupby得到分组后的数据 pandas—groupby如何得到分组里的数据 date_range补齐缺失日期 在处理时间序列的数据中&#xff0c;有时候会遇到有些日期的数…

springboot源码编译问题

问题一 Could not find artifact org.springframework.boot:spring-boot-starter-parent:pom:2.2.5.RELEASE in nexus-aliyun (http://maven.aliyun.com/nexus/content/groups/public/) 意思是无法在阿里云的镜像仓库中找到资源 解决&#xff1a;将配置的镜像删除即可&#…

iOS开发Swift-函数

1.函数的定义和调用 func greet(person: String) -> String { // 函数名 传入值 传入值类型 返回值类型let greeting "Hello" personreturn greeting } print( greet(person: "Anna") ) //调用2.函数的参数与返回值 (1)无参函数 func sayHe…

STM32 CAN 波特率计算分析

这里写目录标题 前言时钟分析时钟元到BIT 前言 CubeMX中配置CAN波特率的这个界面刚用的时候觉得非常难用&#xff0c;怎么都配置不到想要的波特率。接下来为大家做一下简单的分析。 时钟分析 STM32F4的CAN时钟来自APB1 在如下界面配置&#xff0c;最好配置为1个整一点的数。…

cpolar做一个内网穿透

因为不在公司&#xff0c;需要访问公司的数据库&#xff0c;所以做一个内网穿透 下载安装 下载地址&#xff1a; https://dashboard.cpolar.com/get-started 下载后是个压缩包&#xff0c;解压后傻瓜式安装 操作隧道 安装后打开Cpolar Web UI 登录账号&#xff0c;查看隧…

如何评估分类模型的好坏

如何评估分类模型的好坏 评估分类预测模型的质量&#xff0c;常用一个矩阵、三条曲线和六个指标。 一个矩阵&#xff1a;混淆矩阵&#xff1b;三条曲线&#xff1a;ROC曲线、PR曲线、KS曲线&#xff1b;六个指标&#xff1a;正确率Acc、查全率R、查准率P、F值、AUC、BEP值、KS…

【设计模式--原型模式(Prototype Pattern)

一、什么是原型模式 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它的主要目的是通过复制现有对象来创建新的对象&#xff0c;而无需显式地使用构造函数或工厂方法。这种模式允许我们创建一个可定制的原型对象&#xff0c;然后通过复制…

SVM详解

公式太多了&#xff0c;就用图片用笔记呈现&#xff0c;SVM虽然算法本质一目了然&#xff0c;但其中用到的数学推导还是挺多的&#xff0c;其中拉格朗日约束关于α>0这块证明我看了很长时间&#xff0c;到底是因为悟性不够。对偶问题也是&#xff0c;用了一个简单的例子才明…

软考A计划-系统集成项目管理工程师-小抄手册(共25章节)-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

求生之路2私人服务器开服搭建教程centos

求生之路2私人服务器开服搭建教程centos 大家好我是艾西&#xff0c;朋友想玩求生之路2(left4dead2)重回经典。Steam玩起来有时候没有那么得劲&#xff0c;于是问我有没有可能自己搭建一个玩玩。今天跟大家分享的就是求生之路2的自己用服务器搭建的一个心路历程。 &#xff0…

C++卷积神经网络

C卷积神经网络 #include"TP_NNW.h" #include<iostream> #pragma warning(disable:4996) using namespace std; using namespace mnist;float* SGD(Weight* W1, Weight& W5, Weight& Wo, float** X) {Vector2 ve(28, 28);float* temp new float[10];V…

React+Typescript 父子组件事件传值

好 之前我们将 state 状态管理简单过了一下 那么 本文 我们来研究一下事假处理 点击事件上文中我们已经用过了 这里 我们就不去讲了 主要来说说 父子之间的事件 我们直接来编写一个小dom 我们父组件 编写代码如下 import Hello from "./components/hello";functio…

记录 JSONObject.parseObject json对象转换 对象字段为null

1.业务背景 使用websocket 接收消息都是String类型&#xff0c;没办法自定义实体类接收&#xff0c;所以接发都必须将json 转 对象 对象转 json。 这是我最开始的实体类&#xff0c;也就是转换的类型 package com.trinity.system.domain;import lombok.AllArgsConstructor; im…

【Midjourney电商与平面设计实战】创作效率提升300%

不得不说&#xff0c;最近智能AI的话题火爆圈内外啦。这不&#xff0c;战火已经从IT行业燃烧到设计行业里了。 刚研究完ChatGPT&#xff0c;现在又出来一个AI作图Midjourney。 其视觉效果令不少网友感叹&#xff1a;“AI已经不逊于人类画师了!” 现如今&#xff0c;在AIGC 热…

浅谈泛在电力物联网发展形态与技术挑战

安科瑞 华楠 摘 要&#xff1a;泛在电力物联网是当前智能电网发展的一个方向。首先&#xff0c;总结了泛在电力物联网的主要作用和价值体现&#xff1b;其次&#xff0c;从智能电网各个环节概述了物联网技术在电力领域的已有研究和应用基础&#xff1b;进而&#xff0c;构思并…

【前端】vscode前端插件笔记

前段vscode好用插件笔记 不需要安装已经自带 HTML SnippetsPath IntellisenseAuto Rename TagBracket Pair Colorizer 核心好用 中文包关键步骤&#xff1a;controlshift然后display language切换即可open in browserLive Server 实时效果显示JS-CSS-HTML Formatter保存后格…

MATLAB算法实战应用案例精讲-【深度学习】自然语言处理模型SimCSE

目录 前言 1.介绍 2.对比学习背景 2.1定义 2.2构造正样本 2.3对齐性和均匀性

小研究 - J2EE 应用服务器的软件老化测试研究

软件老化现象是影响软件可靠性的重要因素&#xff0c;长期运行的软件系统存在软件老化现象&#xff0c;这将影响整个业务系统的正常运行&#xff0c;给企事业单位带来无可估量的经济损失。软件老化出现的主要原因是操作系统资源消耗殆尽&#xff0c;导致应用系统的性能下降甚至…