C++(学习)2024.9.23
目录
运算符重载
1.概念
2.友元函数运算符重载
3.成员函数运算符重载
4.特殊运算符重载
1.赋值运算符重载
2.类型转换运算符重载
5.注意事项
std::string字符串类:
模板与容器
模板
1.函数模板
2.类模板
类内实现
类内声明类外实现
运算符重载
1.概念
C++中可以把部分的运算符开做成函数,此时运算符也可以重载。
运算符预定义的操作只能针对基本数据类型。但是对于自定义类型,也需要类似运算操作,此时就可以重新定义这些运算符的功能,使其支持特定类型,完成特定的操作。
可以被重载的运算符:
算术运算符:+、-、*、/、%、++、--
位操作运算符:&、|、~、^(位异或)、<<(左移)、>>(右移)
逻辑运算符:!、&&、||
比较运算符:<、>、>=、<=、==、!=
赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
其他运算符:[]、()、->、,、new、delete、new[]、delete[]不被重载的运算符:
成员运算符"."、指针运算符"*"、三目运算符" ? : "、sizeof、作用域"::"
运算符重载有两种实现方式:
1.友元函数运算符重载
2.成员函数运算符重载
2.友元函数运算符重载

#include <iostream>
using namespace std;class MyInt
{
private:int a;
public:MyInt(int a){this->a=a;}int get_int(){return a;}friend MyInt operator +(MyInt &i,MyInt &i2);friend MyInt operator ++(MyInt &i);//前置++friend MyInt operator ++(MyInt &i,int);//后置++
};
MyInt operator +(MyInt &i,MyInt &i2)
{return i.a+i2.a;
}
MyInt operator ++(MyInt &i)
{return ++i.a;
}MyInt operator ++(MyInt &i,int)
{return i.a++;
}int main()
{MyInt int1(1);MyInt int2(2);MyInt int3=int1+int2;cout<<"int1: "<<int1.get_int()<<endl;cout<<"int2: "<<int2.get_int()<<endl;cout<<"int3=int1+int2"<<endl;cout<<"++int3: "<<(++int3).get_int()<<endl;cout<<"int3++: "<<(int3++).get_int()<<endl;cout<<"int3: "<<int3.get_int()<<endl;return 0;
}
3.成员函数运算符重载
成员函数运算符重载相比于友元函数运算符重载,最主要的区别,在于友元函数的第一个输入参数,在成员函数中使用this指针代替,因此同样的运算符重载,成员函数比友元函数参数少一个。

#include <iostream>
using namespace std;class MyInt
{
private:int a;
public:MyInt(int a){this->a=a;}int get_int(){return a;}MyInt operator +(MyInt &i);MyInt operator ++();//前置++MyInt operator ++(int);//后置++
};
MyInt MyInt::operator +(MyInt &i)
{return this->a+i.a;
}
MyInt MyInt::operator ++()
{return ++this->a;
}MyInt MyInt::operator ++(int)
{return this->a++;
}int main()
{MyInt int1(1);MyInt int2(2);MyInt int3=int1+int2;cout<<"int1: "<<int1.get_int()<<endl;cout<<"int2: "<<int2.get_int()<<endl;cout<<"int3=int1+int2"<<endl;cout<<"++int3: "<<(++int3).get_int()<<endl;cout<<"int3++: "<<(int3++).get_int()<<endl;cout<<"int3: "<<int3.get_int()<<endl;return 0;
}
4.特殊运算符重载
1.赋值运算符重载
除了之前学习的无参构造函数、拷贝构造函数、析构函数以外,如果程序员不手写,编译器还会添加一个赋值运算符重载函数。
赋值运算符重载只能使用成员函数运算符实现。
当类中出现指针类型的成员变量时,默认的赋值运算符重载函数,类似于默认的浅拷贝构造函数,因此需要手动编写解决“浅拷贝”的问题。
#include <iostream>
using namespace std;class MyInt
{int a;
public:MyInt(int a){this->a=a;}int get_int(){return a;}MyInt &operator =(MyInt &i){cout<<"调用赋值运算符重载函数"<<endl;this->a=i.a;return *this;}
};int main()
{MyInt int1(1);MyInt int2(2);cout<<"int1: "<<int1.get_int()<<endl;cout<<"int2: "<<int2.get_int()<<endl;int2=int1;cout<<"int2: "<<int2.get_int()<<endl;return 0;
}
2.类型转换运算符重载
必须使用成员函数运算符重载,且格式比较特殊。
#include <iostream>
using namespace std;class MyInt
{int a;string b="hello";
public:MyInt(int a){this->a=a;}operator int(){return a;}operator string(){return b;}
};int main()
{MyInt int1(1);int a=int1;string b=int1;cout<<"int a = "<<a<<endl;cout<<"string b = "<<b<<endl;return 0;
}
5.注意事项
1.重载的运算符限制在C++语言中已有的运算符范围,不能创建新的运算符。
2.运算符重载本质上也是函数重载,但是不支持函数默认值设定。
3.重载之后运算符不能改变运算符的优先级和结合性,也不能改变运算符的操作数和语法结构。
4.运算符重载必须基于或包含自定义类型,即不能改变基本数据类的运算规则。
5.重载的功能应该与原有的功能相似,避免没有目的的滥用运算符重载。
6.一般情况下,双目运算符建议使用友元函数运算符重载,单目运算符建议使用成员函数运算符重载。
std::string字符串类:
字符串对象是一种特殊类型的容器,专门设计用于操作字符串。
#include <iostream>
#include <string.h>
using namespace std;int main()
{string s;// 判断是否为空cout<<s.empty()<<endl; //1string s1="hello";//隐式调用构造函数cout<<s1<<endl; //hellostring s2("world");//显式调用构造函数cout<<s2<<endl; //world//==、!=、> 、< 判断cout<<(s1==s2)<<endl; //0cout<<(s1!=s2)<<endl; //1cout<<(s1>s2)<<endl; //0cout<<(s1<s2)<<endl; //1string s3(s2);//拷贝构造函数cout<<s3<<endl; //world// 参数1:char * 源字符串// 参数2:保留的字符串数string s4("ABCDE",3);cout<<s4<<endl; //ABC// 参数1:std::string 源字符串// 参数2:不保留的字符数,从头开始string s5(s2,3);cout<<s5<<endl; //ld// 参数1:字符数量// 参数2:字符内容 charstring s6(5,'a');cout<<s6<<endl; //aaaaacout << "原s5 = " << s5 << " " << "原s6 = " << s6 << endl;swap(s5,s6); // 交换cout << "交换后s5 = " << s5 << " " << "交换后s6 = " << s6 << endl;string s7=s1+s2;//字符串连接cout<<s7<<endl; //helloworlds7.append("你好世界");// 向后追加字符串cout<<s7<<endl; //helloworld你好世界s7.push_back('a');// 向后追加单个字符cout<<s7<<endl; //helloworld你好世界a// 插入// 参数1:插入的位置// 参数2:插入的内容s7.insert(0,"123");cout<<s7<<endl; //123helloworld你好世界a// 删除字符串// 参数1:起始位置// 参数2:删除的字符数量s7.erase(2,5);cout<<s7<<endl; //12oworld你好世界a// 替换// 参数1:起始位置// 参数2:被替换的字符数// 参数3:替换的新内容s7.replace(0,3,"++++");cout<<s7<<endl; //++++world你好世界as7.clear(); // 清空cout<<s7.length()<<endl; //0string s8="heiheihei";cout<<s8<<endl; //heiheiheis8="ABCDEFG"; // 重新赋值cout<<s8<<endl; //ABCDEFG// 参数1:拷贝的目标// 参数2:拷贝的字符数量// 参数3:拷贝的起始位置// C++的string到C语言数组char a[20]={0};s8.copy(a,3,0);cout<<a<<endl; //ABC// C++ string 到 c string 用到了C语言中的strcpy// c_str C++的字符串转成C语言的字符数组// c_str 返回一个 const char *char b[20]={0};strcpy(b,s8.c_str());cout<<b<<endl; //ABCDEFGreturn 0;
}
模板与容器
模板
模板可以让类或者函数支持一种通用类型,这种通用类型在实际运行的过程中可以使用任何数据类型,因此可以写一些与类型无关的代码,这种编程方式也被称为“泛型编程”。
通常有两种形式:
1.函数模板
2.类模板
1.函数模板
使一个函数支持模板编程,可以使函数支持通用数据类型。
#include <iostream>
using namespace std;
template<typename T> // typename也可以是class
T add(T a,T b)
{return a + b;
}int main()
{string str1 = "hello";string str2 = "world";cout << add(str1,str1) << endl;return 0;
}
2.类模板
使一个类支持模板编程,可以使一个类支持通用数据类型。
类内实现
#include <iostream>
using namespace std;template<class T>
class Test
{
private:T val;
public:Test(T v){val = v;}T get_val()const{return val;}void set_val(const T &val){this->val = val;}
};int main()
{Test<int> t1(20);cout << t1.get_val() << endl;t1.set_val(10);cout << t1.get_val() << endl;t1.set_val(10.32);cout << t1.get_val() << endl; // 数据窄化10Test<double> t2(2.56);cout << t2.get_val() << endl;t2.set_val(23.12);cout << t2.get_val() << endl;return 0;
}
类内声明类外实现
#include <iostream>
using namespace std;template<class T>
class Test
{
private:T val;
public:Test(T v);T get_val()const;void set_val(const T &val);
};template<class T>
Test<T>::Test(T v)
{val = v;
}template<class T>
T Test<T>::get_val()const
{return val;
}template<class T>
void Test<T>::set_val(const T &val)
{this->val = val;
}int main()
{Test<int> t1(20);cout << t1.get_val() << endl;t1.set_val(10);cout << t1.get_val() << endl;t1.set_val(10.32);cout << t1.get_val() << endl; // 数据窄化10Test<double> t2(2.56);cout << t2.get_val() << endl;t2.set_val(23.12);cout << t2.get_val() << endl;return 0;
}相关文章:
C++(学习)2024.9.23
目录 运算符重载 1.概念 2.友元函数运算符重载 3.成员函数运算符重载 4.特殊运算符重载 1.赋值运算符重载 2.类型转换运算符重载 5.注意事项 std::string字符串类: 模板与容器 模板 1.函数模板 2.类模板 类内实现 类内声明类外实现 运算符重载 1.概念…...
大数据处理从零开始————3.Hadoop伪分布式和分布式搭建
1.伪分布式搭建(不会用,了解就好不需要搭建) 这里接上一节。 1.1 伪分布式集群概述 伪分布式集群就是只有⼀个服务器节点的分布式集群。在这种模式中,我们也是只需要⼀台机器。 但与本地模式不同,伪分布式采⽤了分布式…...
跟着问题学12——GRU详解
1 GRU 1. 什么是GRU GRU(Gate Recurrent Unit)是循环神经网络(Recurrent Neural Network, RNN)的一种。和LSTM(Long-Short Term Memory)一样,也是为了解决长期记忆 和反向传播中的梯度等问题…...
内核是如何接收网络包的
1、数据如何从网卡到网络协议栈 1.1内核收包的过程 1、数据帧从外部网络到达网卡 2、网卡把数据帧从自己的缓存DMA(拷贝到)和内核共有的RingBuffer上 3、网卡发出硬中断通知CPU 4、CPU响应硬中断,简单处理后发出软中断 5、k’softirqd线程处理软中断,调…...
计算机毕业设计之:基于微信小程序的电费缴费系统(源码+文档+讲解)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
【leetcode】环形链表、最长公共前缀
题目:环形链表 解法一:哈希表 创建一个哈希表,遍历链表先判断哈希表中是否含有要放入哈希表中的节点,如果该节点已在哈希表中出现那么说明该链表是环形的;如果链表节点出现nullptr那么就退出循环,该链表是…...
C#开发记录如何建立虚拟串口,进行串口通信,以及通信模板
记录时间;2024年4月 记录如何开启虚拟串口以及进行基础串口通信。 建立虚拟串口 使用的软件是vspd,建立虚拟串口之后就可以将他们当成实际物理连接的两个串口进行通信。 之后使用我们之前给出的通信模板,建立一个稍微规矩一点的界面。 界面建立 其中…...
电源设计的艺术:从底层逻辑到工程实践
在电子工程的世界里,电源设计是核心中的核心。它不仅是电子设备的能量源泉,更是整个系统稳定运行的基石。随着科技的不断进步,电源设计的要求也越来越高,从效率、稳定性到体积、成本,每一个维度都是工程师们不断追求的…...
软媒市场新探索:软文媒体自助发布,开启自助发稿新篇章
在繁华喧嚣的软媒市场中,每一个声音都在竭力呼喊,每一个品牌都在奋力展现。而软文,作为一种温柔而坚韧的营销力量,正逐渐崭露头角。特别是软文媒体自助发布平台的出现,更是为企业提供了一个全新的、高效的自助发稿渠道。 软媒市场自助发布平台,正如其名,是一个让企业能够自主发…...
【Kubernetes】常见面试题汇总(二十七)
目录 77.假设公司希望在不同的云基础架构上运行各种工作负载,从裸机到公共云。公司将如何在不同界面的存在下实现这一目标? 78.什么是 Google 容器引擎? 特别说明: 题目 1-68 属于【Kubernetes】的常规概念题。 题目 69-1…...
基于单片机巡迹避障智能小车系统
文章目录 前言资料获取设计介绍设计程序具体实现截图设计获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们…...
Python163邮箱发送:提升发送效率的技巧?
python163邮箱发送邮件教程?python怎么使用163邮箱? Python163邮箱发送作为一种自动化邮件发送方式,越来越受到开发者和企业的青睐。AokSend将探讨如何通过多种技巧提升Python163邮箱发送的效率,从而更好地满足用户需求。 Pytho…...
springboot中的异步任务
在springboot项目中可以通过EnableAsyncAsync的方式简化异步操作,下文使用springboot:3.2.1 源码分析 若一个bean中的公共方法上标注了Async,在系统启动时,会给这个类创建一个代理对象,并将该代理对象作为bean注册到spring容器中 …...
Linux学习笔记8 理解Ubuntu网络管理,做自己网络的主人
本文讲解了Ubuntu下网络由什么管理,介绍了临时ip和路由的设置方法,介绍了静态持久化网络配置的方法以及各网络管理软件之间的关系。 来看看Ubuntu网络管理。 序言 原本学习ubuntu网络管理就是为了检查nginx安装过程中使用wget获取压缩包为什么解析不出…...
理解线程的三大特性:原子性、可见性和有序性
在并发编程中,保护线程安全是一个重要课题。要实现线程安全,我们必须理解并掌握三个核心概念:原子性、可见性和有序性。下面将详细介绍这三个特性及其解决方案。 一、原子性 原子性是指一个操作要么全部完成,要么完全不执行。在多…...
英特尔®以太网网络适配器E810-CQDA1 / E810-CQDA2 网卡 规格书 e810 网卡 规格书 Intel100G E810 网卡 白皮书
英特尔以太网800系列网络适配器 英特尔以太网网络适配器E810-CQDA1 / CQDA2 在10到100Gbps的以太网速度下实现高效的工作负载优化性能 关键特性 •单、双端口QSFP28 •应用设备队列(ADQ) •PCI Express (PCIe) 4.0 x16 •动态设备个性化(DDP) •以太网端口配置工具(EPC…...
好用的idea方法分隔符插件
好用的idea方法分隔符插件...
通过 Xshell 无法连接到 Ubuntu
无法通过 Xshell 连接到 Ubuntu 服务器,通常与 SSH 服务、网络连接、主机防火墙设置问题有关。以下是排查并解决这个问题的步骤: 1. 确保 SSH 服务正在运行 在 Ubuntu 上,SSH 服务必须启动才能连接。如果你有虚拟机或物理机的访问权限&…...
Java面试篇基础部分-Synchronized关键字详解
Synchronized关键字用于对Java对象、方法、代码块等提供线程安全操作。Synchronized属于独占式的悲观锁机制,同时也是可重入锁。我们在使用Synchronized关键字的时候,可以保证同一时刻只有一个线程对该对象进行访问;也就是说它在同一个JVM中是线程安全的。 Java中的每个…...
数据结构之线性表——LeetCode:67. 二进制求和,27. 移除元素,26. 删除有序数组中的重复项
67. 二进制求和 题目描述 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 运行代码(javaC) class Solution {public String addBinary(String a, String b) {StringBuilder ansnew StringBuilder();int ca0;for(i…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...
