C++11QT复习 (四)
Day6-1 输入输出流运算符重载(2025.03.25)
1. 拷贝构造函数的调用时机
2. 友元2.1 友元函数
3. 输入输出流运算符重载3.1 关键知识点3.2 代码3.3 关键问题3.4 完整代码
4. 下标访问运算符 `operator[]`4.1 关键知识点4.2 代码
5. 函数调用运算符 `operator()`5.1 关键知识点5.2 代码5.3 示例5.4 完整代码
6. 总结
1. 回顾
1.1 拷贝构造函数的调用时机
拷贝构造函数在以下情况会被调用:
-
对象初始化
- 当用一个已经存在的对象去初始化一个刚刚创建的对象时,调用拷贝构造函数。
- 例:
Complex c1(1, 2); Complex c2 = c1; // 调用拷贝构造函数
-
函数参数传递
- 当形参与实参都是对象时,在函数调用时会调用拷贝构造函数。
- 例:
void func(Complex c) { } func(c1); // 形参与实参结合时调用拷贝构造函数
-
函数返回对象
- 当函数返回一个对象时,可能调用拷贝构造函数(但现代 C++ 编译器会尝试优化此过程,如返回值优化 RVO)。
- 例:
Complex func() {Complex c(3, 4);return c; // 可能调用拷贝构造函数 }
2. 友元
2.1 友元函数
- 友元函数可以访问类的私有成员。
- 友元声明可以出现在类的
public、protected或private部分,不影响其权限。 - 友元关系是单向的、不可传递的:
- 单向:如果
A是B的友元,B并不会自动成为A的友元。 - 不可传递:如果
A是B的友元,B是C的友元,A并不会自动成为C的友元。
- 单向:如果
3. 输入输出流运算符重载
3.1 关键知识点
-
operator<<必须是友元函数- 由于
cout << c1;左操作数是std::ostream,不能修改std::ostream,所以operator<<不能是Complex的成员函数。
- 由于
-
operator>>不能是const成员函数- 因为
operator>>需要修改对象的值,因此不能加const。
- 因为
3.2 代码
std::ostream& operator<<(std::ostream& os, const Complex& rhs) {if (rhs._imag > 0) {os << rhs._real << " + " << rhs._imag << "i";} else if (rhs._imag == 0) {os << rhs._real;} else {os << rhs._real << " - " << -rhs._imag << "i";}return os;
}std::istream& operator>>(std::istream& is, Complex& rhs) {std::cout << "请输入复数的实部和虚部:" << std::endl;is >> rhs._real >> rhs._imag;return is;
}
3.3 关键问题
-
为什么
operator<<和operator>>的返回值是std::ostream&和std::istream&?- 这样可以实现连续输入输出:
cout << c1 << c2 << endl; // 连续输出 cin >> c1 >> c2; // 连续输入
- 这样可以实现连续输入输出:
-
为什么
operator<<的ostream&参数不能去掉&?- 因为
ostream的拷贝构造函数已被delete,不能复制ostream对象。
- 因为
3.4 完整代码
#include <iostream>
#include <limits.h>
#include <ostream>using namespace std;//复数
class Complex
{friend Complex operator*(const Complex& lhs, const Complex& rhs);//Complex operator/(const Complex& rhs) const;
public:Complex(double r = 0, double i = 0): _real(r), _imag(i){cout << "Complex(double r = 0, double i = 0)" << endl;}~Complex(){cout << "~Complex()" << endl;}void display() const{if (_imag > 0){cout << _real << " + " << _imag << "i" << endl;}else if (_imag == 0){cout << _real << endl;}else{cout << _real << " - " << -_imag << "i" << endl;}}//成员函数,operator输出运算符重载 //cout << c1 << endl; //第一个参数cout ,第二个参数c1//std::ostream& operator<<(std::ostream& os, const Complex& rhs); //error!隐含this指针//对于输出流运算符函数而言,不能写成成员函数的形式,因为违背了运算符重载的原则,不能改变操作数的顺序//std::ostream& operator<<(std::ostream& os);//error!this指针在参数列表的第一个位置/*友元函数可以放在类的 任何位置(public / protected / private),不影响其功能。从代码规范角度,建议统一放在类定义的开头或结尾,以提高可读性。友元关系是单向的,且不具备传递性(即类 A 的友元函数不会自动成为类 B 的友元)。*/friend std::ostream& operator<<(std::ostream& os, const Complex& rhs);//输入流运算符重载friend std::istream& operator>>(std::istream& is, Complex& rhs);private:double _real;double _imag;
};
//问题1 :参数列表中ostrream的引用符号&能不能去掉?
//解答1 :不能去掉因为形参"os"和实参"cout"结合的时候会满足拷贝构造函数的调用时机,但是ostream中的拷贝构造函数已被delete//问题2 : 函数返回类型中的引用符号&能不能删除?
//解答2 : 不能取掉,因为return os,返回类型满足拷贝构造函数的调用时机3//注释:basic_ifstream( const basic_ifstream& rhs ) = delete; (7) (since C++11)
// basic_ofstream( const basic_ofstream& rhs ) = delete; (7) (since C++11)
//ifstram 和 ofstream 的拷贝构造函数已经从C++11开始删除了
std::ostream& operator<<(std::ostream& os, const Complex& rhs)
{cout << "std::ostream& operator<<(std::ostream& os, const Complex& rhs)" << endl;if (rhs._imag > 0){os << rhs._real << " + " << rhs._imag << "i" << endl;}else if (rhs._imag == 0){os << rhs._real << endl;}else{os << rhs._real << " - " << -rhs._imag << "i" << endl;}return os;
}void readDouble(std::istream& is, double& rhs)
{while (is >> rhs, !is.eof()){if (is.bad()){std::cerr << "istream is bad" << endl;return;}else if (is.fail()){is.clear();//重置流的状态is.ignore(std::numeric_limits<::std::streamsize>::max(), '\n');//清空缓冲区cout << "请注意:需要输入double类型的数据!";}else{cout << "rhs = " << rhs << endl;break;}}
}//输入流运算符重载
std::istream& operator>>(std::istream& is, Complex& rhs)//因为要修改rhs 的值,所以不能加const
{cout << "std::istream& operator>>(std::istream& is, Complex& rhs)" << endl;cout << "请分别输入复数的实部和虚部:" << endl;//is >> rhs._real >> rhs._imag;readDouble(is, rhs._real);readDouble(is, rhs._imag);return is;
}void testOutputOperator()
{Complex c1(1, 2);cout << "c1 = ";c1.display();cout << endl << endl;//cout << "c1 = " << c1.display();//为什么没有做输出流运算符重载之前上面的写法 不可行呢? 解答:二元“<<”: 没有找到接受“void”类型的右操作数的运算符(或没有可接受的转换)cout << "c1 = " << c1 << endl;cout << endl;Complex c2;cin >> c2;cout << "c2 = " << c2 << endl;
}int main(int argc, char* argv[])
{testOutputOperator();return 0;
}
4. 下标访问运算符 operator[]
4.1 关键知识点
operator[]主要用于自定义数组类型,使得obj[idx]访问数组元素。- 返回值应为
T&,以保证能够修改数组内容。 - 必须进行越界检查,以防止访问非法内存。
4.2 代码
char& CharArrar::operator[](size_t idx) {if (idx < _size) {return _data[idx];} else {static char charNull = '\0';return charNull;}
}
5. 函数调用运算符 operator()
5.1 关键知识点
- 使对象像函数一样调用,称为仿函数(函数对象)。
- 可存储状态,例如调用次数。
5.2 代码
class FunctionObject {
public:int operator()(int x, int y) {++_cnt;return x + y;}int operator()(int x, int y, int z) {++_cnt;return x * y * z;}private:int _cnt = 0;
};
5.3 示例
FunctionObject fo;
cout << "fo(3, 4) = " << fo(3, 4) << endl;
cout << "fo(3, 4, 5) = " << fo(3, 4, 5) << endl;
5.4 完整代码
//bracket.h
#pragma once
#include <iostream>
#include <string.h>using namespace std;
class CharArrar
{
public:CharArrar(size_t sz = 10):_size(sz), _data(new char[_size]){cout << " CharArrar(size_t sz = 10)" << endl;}~CharArrar(){cout << "~CharArrar()" << endl;if (_data){delete _data;_data = nullptr;}}size_t size() const{return _size;}//下标访问运算符的重载//int arr[10] = { 1,2,3,4,5 };//arr.operator[](idx);char& operator[](size_t idx);
private:size_t _size;char* _data;
};
//bracket.cpp
#include "bracket.h"/*
要修复错误 C2106: “=”: 左操作数必须为左值,需要确保 CharArrar 类的
下标运算符 operator[] 返回一个可修改的左值。当前的 operator[] 声明
返回的是一个 char,这不是一个可修改的左值。我们需要将其修改为返回一个 char&。
*/
char& CharArrar::operator[](size_t idx)
{if (idx < _size){return _data[idx];}else{static char charNUll = '\0';//静态变量延长生命周期return charNUll; //使得返回的实体生命周期比函数的生命周期长}
}//C++中优势:重载的下标访问运算符考虑了越界的问题
//引用什么时候需要加上?
//1.如果返回类型是类型的时候,可以减少拷贝构造函数的执行
//2.有可能需要一个左值(来调用右操作数),而不是拷贝后的右值、
//3.cout << "111" << c1 << endl << 10 << 1 << endl,像这种情况下连续使用的时候可以加上引用
//parenthese.h
#pragma once
#include <iostream>using namespace std;class FunctionObject
{
public:int operator()(int x, int y);int operator()(int x, int y, int z);private:int _cnt;//记录被调用的次数(函数对象状态)
};
parenthese.cpp
#include <iostream>
#include "parenthese.h"using namespace std;int FunctionObject::operator()(int x, int y)
{++_cnt;cout << "int operator()(int x, int y)" << endl;return x + y;
}int FunctionObject::operator()(int x, int y, int z)
{cout << "int operator()(int x, int y,int z)" << endl;++_cnt;return x * y * z;
}
//main.cpp
#include <iostream>
#include "bracket.h"
#include "parenthese.h"using namespace std;int add(int x, int y)
{cout << "int add(int x,int y)" << endl;static int cnt = 0;++cnt;return x + y;
}void testFunctionObject()
{FunctionObject fo;int a = 3;int b = 4;int c = 5;//fo本质上是一个对象,但是他的使用cout << "fo(a,b) = " << fo(a, b) << endl;cout << "fo(a, b ,c) = " << fo(a, b, c) << endl;cout << endl;//正经的函数cout << "add(a, b) = " << add(a, b) << endl;
}void testCharArrar()
{//把字符串中的内容拷贝到CharArrayconst char* pstr = "hello cpp";CharArrar ca(strlen(pstr) + 1);for(size_t idx = 0; idx != ca.size(); ++idx){//ca[idx] = pstr[idx];//上面和下面两条代码等价ca.operator[](idx) = pstr[idx];}for (size_t idx = 0; idx != ca.size(); ++idx){cout << ca[idx] << " ";}cout << endl;
}int main(int argc, char** argv)
{testFunctionObject();testCharArrar();return 0;
}
相关文章:
C++11QT复习 (四)
Day6-1 输入输出流运算符重载(2025.03.25) 1. 拷贝构造函数的调用时机 2. 友元2.1 友元函数 3. 输入输出流运算符重载3.1 关键知识点3.2 代码3.3 关键问题3.4 完整代码 4. 下标访问运算符 operator[]4.1 关键知识点4.2 代码 5. 函数调用运算符 operator…...
LVS的 NAT 模式实验
文章目录 目录 文章目录 概要 IP规划与题目分析 实验步骤 一、nginx配置(rs1、rs2、rs3) 二、LVS配置 三、客户端配置 四、防火墙和selinux配置 实验结果 痛点解答 概要 LVS/NAT lvs/nat网络地址转换模式,进站/出站的数据流量经过分发器(IP负…...
【MacOS】2025年硬核方法清理MacOS中的可清除空间(Purgeable space)
背景 MacOS使用一段时间之后,硬盘空间会越来越少,但自己的文件没有存储那么多,在储存空间中可以发现可用空间明明还剩很多,但磁盘工具却显示已满,见下图。 尝试解决 df -h 命令却发现磁盘已经被快被占满。使用du命…...
ue材质学习感想总结笔记
2025 - 3 - 27 1.1 加法 对TexCoord上的每一个像素加上一个值,如果加上0.1,0.1, 那么左上角原来0,0的位置变成了0.1,0.1 右上角就变成了1.1,1.1,那么原来0,0的位置就去到了左上角左上边,所以图像往左上偏移。 总而言…...
Go 语言 sync 包使用教程
Go 语言 sync 包使用教程 Go 语言的 sync 包提供了基本的同步原语,用于在并发编程中协调 goroutine 之间的操作。 1. 互斥锁 (Mutex) 互斥锁用于保护共享资源,确保同一时间只有一个 goroutine 可以访问。 特点: 最基本的同步原语&#x…...
约束文件SDC常用命令
约束文件SDC常用命令 定义时钟create_clock -name CLK-period 2 [get_ports_clk]告诉工具主时钟周期是2ns(频率500MHz),从clk端口输入 输入信号延迟set_input_delay 0.5 -clock CLK [get_ports data_in]数据进芯片前,外部电路已消耗0.5ns,综合要预留这段“堵车时间”。 输出…...
信而泰PFC/ECN流量测试方案:打造智能无损网络的关键利器
导语: AI算力爆发的背后,如何保障网络“零丢包”? 在当今数据中心网络中,随着AI、高性能计算(HPC)和分布式存储等应用的飞速发展,网络的无损传输能力变得至关重要。PFC(基于优先级的…...
golang不使用锁的情况下,对slice执行并发写操作,是否会有并发问题呢?
背景 并发问题最简单的解决方案加个锁,但是,加锁就会有资源争用,提高并发能力其中的一个优化方向就是减少锁的使用。 我在之前的这篇文章《开启多个协程,并行对struct中的每个元素操作,是否会引起并发问题?》中讨论过多协程场景下struct的并发问题。 Go语言中的slice在…...
Android 底部EditView输入时悬浮到软键盘上方
1. 修改 Activity 的 Manifest 配置 确保你的 Activity 在 AndroidManifest.xml 中有以下配置: <activityandroid:name".YourActivity"android:windowSoftInputMode"adjustResize|stateHidden" /> 关键点: adjustResize 是…...
CNN和LSTM的计算复杂度分析
前言:今天做边缘计算的时候,在评估模型性能的时候发现NPU计算的大部分时间都花在了LSTM上,使用的是Bi-LSTM(耗时占比98%),CNN耗时很短,不禁会思考为什么LSTM会花费这么久时间。 首先声明一下实…...
UniApp 表单校验两种方式对比:命令式与声明式
目录 前言1. 实战2. Demo 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 以下主要针对Demo讲解,从实战中的体会 何为命令式 何为声明式 命令式的体验,随时都会有提交的按钮ÿ…...
【树莓派Pico FreeRTOS】-Mutex(互斥体)
Mutex(互斥体) 文章目录 Mutex(互斥体)1、硬件准备2、软件准备3、FreeRTOS的Mutex介绍4、完整示例RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (P…...
LCR 187. 破冰游戏(python3解法)
难度:简单 社团共有 num 位成员参与破冰游戏,编号为 0 ~ num-1。成员们按照编号顺序围绕圆桌而坐。社长抽取一个数字 target,从 0 号成员起开始计数,排在第 target 位的成员离开圆桌,且成员离开后从下一个成员开始计数…...
【漏洞修复】为了修复ARM64 Android10系统的第三方库漏洞,将ARM64 Android16的系统库直接拷贝到Android10系统如何?
直接替换系统库的风险分析 将高版本Android(如Android 16)的系统库直接拷贝到低版本系统(如Android 10)可能会导致以下问题: 符号与依赖不兼容 高版本库可能依赖更高版本的NDK或Bionic libc(Android的C库&…...
Flutter环境配置
配置环境变量 PUB_HOSTED_URLhttps://pub.flutter-io.cnFLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn 这个命令是用来配置 Flutter 的镜像源地址,主要是为了解决在中国大陆地区访问 Flutter 官方资源较慢的问题。 具体的操作如下: 右键点…...
centOS 7.9 65bit 修复Openssh漏洞
一、背景: 在使用centos 7.9 64bit版本操作系统时有扫描出如下的漏洞: 二、修复openssh漏洞操作 升级注意事项 (一下所有的操作默认都是root或者管理员权限,如果遇到权限问题每个指令以及指令组合都要在前面加sudo) 1、查看CentOS操作系统信…...
金融级密码管理器——生物特征密钥绑定方案
目录 金融级密码管理器 —— 生物特征密钥绑定方案一、模块概述与设计目标1.1 模块背景与意义1.2 设计目标二、系统架构设计2.1 系统模块划分2.2 系统架构图(Mermaid示意图)三、核心算法与安全原理3.1 生物特征数据预处理3.2 密钥生成算法3.3 安全认证与密钥绑定验证3.4 密钥…...
JDBC-添加数据
文章目录 准备数据库添加数据引入数据库依赖包 准备数据库 自行安装软件,利用小皮内嵌的数据 添加数据 引入数据库依赖包 结构 drivercom.mysql.cj.jdbc.Driver urljdbc:mysql://127.0.0.1:3308/yanyuuserroot passwordrootpackage com.yanyu;import java.sql.*;…...
衡石科技HENGSHI SENSE异构数据关联技术深度解析:揭秘5-8倍性能提升背后的“异构过滤“架构
引言:多源数据关联的行业痛点 在大数据时代,企业数据通常分散在多个异构系统中——关系型数据库、NoSQL、数据仓库、湖仓一体平台等。根据Forrester调研,超过78%的企业需要同时访问5种以上不同类型的数据源进行分析,但传统ETL和跨…...
基于Netlify + Localtunnel 实现本地项目“无服务器”部署上线
基于Netlify Localtunnel 实现本地项目“无服务器”部署上线 1. 先看效果图2. 实现步骤2.1 分两步走2.2 netlify 部署前端资源2.3 Localtunnel 映射 localhost 服务 3. 其它工具内网穿透工具对比4. 总结5. 参考资料 1. 先看效果图 地址:zqchat 2. 实现步骤 2.1 …...
C#从入门到精通(3)
目录 第九章 窗体 (1)From窗体 (2)MDI窗体 (3)继承窗体 第十章 控件 (1)控件常用操作 (2)Label控件 (3)Button控件 &…...
设计模式之创建型5种
设计模式 为什么设计模式是23种创建型 对象创建为什么设计模式是23种 设计模式之所以被归纳为23种,而非其他数量,源于GoF(Gang of Four)在1994年的系统性总结和分类。这一数量的确定并非偶然,而是基于以下核心原因: 他们遵循“大三律”(Rule of Three),即只有经过三个…...
Java + LangChain 实战入门,开发大语言模型应用!
在 Baeldung 上看到了一篇介绍基于 Java LangChain 开发大语言模型应用的基础入门文章,写的非常不错,非常适合初学者。于是,我抽空翻译了一下。 原文地址:https://www.baeldung.com/java-langchain-basics翻译: Java…...
el-date-picker时间范围 编辑回显后不能修改问题
el-date-picker daterange时间范围 编辑回显后不能修改 <el-form-item:label"LABELS.gplanRecordDateLabel"prop"gplanRecordDate"><el-date-pickerstyle"width: 300px"v-model"formData.gplanRecordDate"type"daterang…...
Java多线程与高并发专题—— CyclicBarrier 和 CountDownLatch 有什么异同?
引入 上一篇我们了解CountDownLatch的原理和常见用法,在CountDownLatch的源码注释中,有提到: 另一种典型用法是将一个问题分解为 N 个部分,用一个Runnable描述每个部分,该Runnable执行相应部分的任务并对闭锁进行倒计…...
leetcode543.二叉树的直径
当前顶点作为拐点时,求左子树加上右子树的高度可以求出该通过该顶点的直径大小,再对该顶点和左右子节点作为拐点时直径大小进行比对,返回最大值 缺点是递归了多次 /*** Definition for a binary tree node.* public class TreeNode {* …...
Java EE 进阶:MyBatis案例练习
表白墙 首先我们先准备一下数据库的数据 创建一个信息表 DROP TABLE IF EXISTS message_info;CREATE TABLE message_info (id INT ( 11 ) NOT NULL AUTO_INCREMENT,from VARCHAR ( 127 ) NOT NULL,to VARCHAR ( 127 ) NOT NULL,message VARCHAR ( 256 ) NOT NULL,delete_fla…...
Dubbo 全面解析:从 RPC 核心到服务治理实践
一、分布式系统与 RPC 框架概述 在当今互联网时代,随着业务规模的不断扩大,单体架构已经无法满足高并发、高可用的需求,分布式系统架构成为主流选择。而在分布式系统中,远程服务调用(Remote Procedure Call࿰…...
路由选型终极对决:直连/静态/动态三大类型+华为华三思科配置差异,一张表彻底讲透!
路由选型终极对决:直连/静态/动态三大类型华为华三思科配置差异,一张表彻底讲透! 一、路由:互联网世界的导航系统二、路由类型深度解析三者的本质区别 三、 解密路由表——网络设备的GPS华为(Huawei)华三&a…...
[微信小程序]对接sse接口
[微信小程序]对接sse接口 在uni开发中,在微信小程序中实现sse接口请求 相关连接 微信小程序对接SSE接口记录 uni中实现sse代码 注意的坑点 接收的并不是字符串,而是ArrayBuffer模拟流推送并不是流推送,会有data:字符扰乱推送并不是完全按照…...
