C++学习日记 | LAB 10 运算符重载与友元函数

资料来源:南科大 于仕琪 C/C++ Program Design

LINK:CPP/week10 at main · ShiqiYu/CPP · GitHub


一、本节内容

       本节首先以一个例子具体演示和回顾操作符重载、友元函数以及重载<<操作符。习题部分则为各种运算符重载以及输入输出重载

1.1 Operator overloading 运算符重载

1.2 member function, non-member function, friend function 成员函数 非成员函数 友元函数

  • 成员函数是定义在类内部的函数。它们可以访问类的所有成员变量和其他成员函数。成员函数可以是普通函数、静态函数或虚函数
  • 非成员函数是在类外部定义的函数。它们不能直接访问类的私有或保护成员,除非通过公有成员函数或友元机制。非成员函数通常用于操作多个类对象或实现某些独立于类的功能
  • 友元函数是被类声明为友元的非成员函数。友元函数可以访问类的私有和保护成员。友元函数通常用于需要直接访问类的内部数据但又不适合作为成员函数的情况 
  • 对=进行重构必须是成员函数

友元函数的优势:

相对于成员函数:

  • 灵活性:友元函数可以定义在类的外部,这使得它们在处理多个类对象时更加灵活。例如,运算符重载函数可以作为友元函数定义,以便处理不同类型的操作数。
  • 类型转换:友元函数可以对左操作数进行类型转换,这在成员函数中是不可能的。对于需要对左操作数进行类型转换的运算符重载,友元函数是一个理想的选择。
  • 减少类的耦合:友元函数可以减少类之间的耦合度。通过友元函数,一个类可以允许另一个类或函数访问其私有成员,而不需要将这些成员公开。这有助于保持类的封装性,同时提供必要的访问权限。

相较于其他非成员函数:

  • 访问私有和保护成员:友元函数可以访问类的私有和保护成员,而不需要通过公共接口。这使得友元函数在需要直接操作类的内部数据时非常有用。

总结:可以理解为友元函数占有了二者的优势。同时,友元函数是非成员函数。

  • 补充:友元类

        除了友元函数,C++还支持友元类。友元类的所有成员函数都可以访问另一个类的私有和保护成员。

  1. 定义:友元类是被另一个类声明为友元的类。友元类的所有成员函数都可以访问该类的私有和保护成员。
  2. 作用范围:友元类的所有成员函数都可以访问它被声明为友元的那个类的私有和保护成员。
  3. 使用场景:友元类通常用于两个类需要紧密协作的情况。例如,一个类需要频繁访问另一个类的内部数据。

对比友元函数和友元类:

  • 友元函数:适用于单个函数需要访问类的私有成员的情况。
  • 友元类:适用于一个类的多个成员函数需要访问另一个类的私有成员的情况。

一个例子:

1.3 Member-wise initialization 初始化

        在使用现有对象对新的对象进行初始化过程中,如果没有写相关的构造函数以提供复制功能,编译器将会自动提供一个默认的以实现复制初始化。

 1.4 Objects assignment 赋值

        在给对象赋值过程中不会调用复制的构造函数。必须对“=”运算符进行重构以实现赋值功能。 

二、习题笔记

  • 成员函数:赋值运算符 (=) 必须定义为成员函数。
  • 友元函数:输入 (>>) 和输出 (<<) 运算符必须定义为友元函数。
  • 其他运算符(如加法、减法、乘法、等于和不等于)可以根据具体需求选择定义为友元函数或成员函数。如果都是用类的对象进行运算,则可以全部定义为成员函数,如果存在int/char/double和类混合运算情况,则定义为友元函数较好。

main.cpp

#include "complex.hpp"int main() {Complex c1(3.0, 4.0), c2(1.0, 2.0), c3;bool c;cout << "c1: " << c1 << endl;cout << "c2: " << c2 << endl;c = c1 == c2;cout << "c1 和 c2 相等? " << c << endl;c = c1 != c2;cout << "c1 和 c2 不相等? " << c << endl;c3 = c1 + c2;cout << "c1 + c2: " << c3 << endl;c3 = c1 - c2;cout << "c1 - c2: " << c3 << endl;c3 = c1 * c2;cout << "c1 * c2: " << c3 << endl;cout << "输入一个复数 (c3):" << endl;cin >> c3;cout << "你输入的是: " << c3 << endl;return 0;
}

complex.hpp

#pragma once#include <iostream>
using namespace std;class Complex
{private:double realPart;double imaginaryPart;public:Complex() : realPart(0.0), imaginaryPart(0.0) {}Complex(double real, double imaginary) : realPart(real), imaginaryPart(imaginary) {}Complex& operator=(const Complex &other) {if (this != &other) {realPart = other.realPart;imaginaryPart = other.imaginaryPart;}return *this;}// the declarations, the definitions are out of the class// 显示复数friend Complex operator+(const Complex &lhs, const Complex &rhs);friend Complex operator-(const Complex &lhs, const Complex &rhs);friend Complex operator*(const Complex &lhs, const Complex &rhs);friend bool operator==(const Complex &lhs, const Complex &rhs);friend bool operator!=(const Complex &lhs, const Complex &rhs);friend std::ostream& operator<<(std::ostream &out, const Complex &c);friend std::istream& operator>>(std::istream &in, Complex &c);};

complex.cpp

#include "complex.hpp"Complex operator+(const Complex &lhs, const Complex &rhs)
{return Complex(lhs.realPart + rhs.realPart, lhs.imaginaryPart + rhs.imaginaryPart);
}Complex operator-(const Complex &lhs, const Complex &rhs)
{return Complex(lhs.realPart - rhs.realPart, lhs.imaginaryPart - rhs.imaginaryPart);
}Complex operator*(const Complex &lhs, const Complex &rhs) 
{return Complex(lhs.realPart * rhs.realPart - lhs.imaginaryPart * rhs.imaginaryPart, lhs.realPart * rhs.imaginaryPart + lhs.imaginaryPart * rhs.realPart);
}bool operator==(const Complex &lhs, const Complex &rhs) 
{return (lhs.realPart == rhs.realPart && lhs.imaginaryPart == rhs.imaginaryPart);
}bool operator!=(const Complex &lhs, const Complex &rhs) 
{return !(lhs == rhs);
}std::ostream& operator<<(std::ostream &out, const Complex &c) 
{if(c.imaginaryPart >= 0)    out << c.realPart << " + " << c.imaginaryPart << "i";elseout << c.realPart << " - " << -c.imaginaryPart << "i";return out;
}std::istream& operator>>(std::istream &in, Complex &c) 
{std::cout << "输入实部: ";in >> c.realPart;std::cout << "输入虚部: ";in >> c.imaginaryPart;return in;
}

运行结果:

编程细节tips:

  • 友元函数的声明通常放在类的任何访问控制区域(public、protected 或 private)都可以。这是因为友元函数的访问权限与它们在类中的声明位置无关。
  • 赋值运算符 operator= 通常返回一个对当前对象的引用(Complex&),这是为了支持链式赋值操作,并确保赋值操作的效率和正确性。

        1. 支持链式赋值:返回当前对象的引用允许链式赋值操作。例如:

Complex c1, c2, c3; 
c1 = c2 = c3; 

        在这个例子中,c2 = c3 返回 c2 的引用,然后 c1 = c2 使用这个引用进行赋值。如果赋值运算符不返回引用,链式赋值将无法正常工作。

        2. 提高效率:返回引用避免了不必要的对象拷贝。赋值运算符直接返回当前对象的引用,而不是返回一个新的对象,从而提高了效率。

        3. 符合C++标准惯例:返回当前对象的引用是C++标准库中赋值运算符的惯例。这种做法确保了代码的一致性和可读性。

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

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

相关文章

支持向量机回归及其应用(附Python 案例代码)

使用支持向量机回归估计房价 让我们看看如何使用支持向量机&#xff08;SVM&#xff09;的概念构建一个回归器来估计房价。我们将使用sklearn中提供的数据集&#xff0c;其中每个数据点由13个属性定义。我们的目标是根据这些属性估计房价。 引言 支持向量回归&#xff08;SV…

WHAT - 一个 Github 仓库的 License 如何解读

目录 一、背景二、解读许可证说明的作用常见的开源许可证类型使用他人代码仓库时需要注意的事项结论 实践作为开发者1. 选择许可证类型2. 在 README 文件中编写许可证信息 作为使用者1. 确定权限2. 了解和遵守条款 总结 一、背景 我们经常在一些 Github 仓库里看到 License 部…

Cache 替换策略--PLRU算法详解

一、引言 LRU&#xff08;Least Recently Used&#xff09;是 cache 的经典替换策略之一&#xff0c;但当 Cache 的路数比较大时&#xff08;多路组相连结构&#xff09;&#xff0c;实现 LRU 的硬件开销就会变得很大。现代处理器一般会考虑使用 PLRU&#xff08;pseudo-LRU&a…

Vue.js 2 项目实战(八):小黑记事本组件版

前言 Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的设计初衷是通过采用简洁且强大的结构&#xff0c;使前端开发变得更简单和高效。以下是对 Vue.js 的详细介绍&#xff1a; 核心特性 声明式渲染 Vue.js 使用声明式语法来描述用户界面&#xff0c;通过数据绑…

用Swagger进行后端接口测试的实战操作

目录 一.什么是Swagger&#xff1f; 二.Swagger的使用操作流程&#xff1a; 1.在pom.xml配置文件导入 Knife4j 的依赖&#xff1a; 2.在config配置类中加入 Knife4j 的相关配置并设置静态资源映射&#xff08;否则接口文档无法访问&#xff09;&#xff1a; 三.Swagger的四个…

xctf--debug

第一眼看着给我吓了一跳 我还以为是什么很牛逼壳 结果就是dnspy打开 这个函数什么ID都没有 只能一个一个点 但是逻辑真的很清晰 之前BUU写的题太复杂了,感觉可以看看这些题静下心 这个时候看着 攻防世界逆向高手题之debug_攻防世界debug-CSDN博客 这个博主的(我好多东西…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 亲子游戏(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

【轨物方案】电气设备数字档案解决方案

需求痛点 传统的电气设备铭牌只能显示固定的名称、日期、型号等信息&#xff0c;不能把与设备相关的其他重要信息展现出来&#xff0c;终端用户想要了解设备信息比较困难。尤其像项目资料类的文件查看&#xff0c;更是有很多不便之处&#xff0c;当设备出现问题后&#xff0c;找…

简要了解sql注入

sql注入安全测试中危害 数据库中的数据&#xff0c;对数据库数据进行操作&#xff08;查询、删除等&#xff09;&#xff1b;网站的权限&#xff0c;找到注入点后可后门写入&#xff1b; sql注入产生原理详细分析 可控变量&#xff0c;带入数据库查询&#xff0c;变量未存在…

前后端打包部署 虚拟机jdk安装及配置环境变量 +安装nginx

mkdir deploy ll mkdir gateway auth system file 去idea打包 不要先打gateway 上传上去 出现这个问题是因为你jdk环境不一样 我的是17 所以我现在去官网下载一个 官网 &#xff1a;Java Downloads | Oracle 中国 mkdir software cd software/ wget https://download.oracl…

橙单前端项目下载编译遇到的问题与解决

今天下载orange-admin前端项目&#xff0c;不过下载下来运行也出现一些问题。 1、运行出现下面一堆错误&#xff0c;如下&#xff1a; 2、对于下面这个错误 error Expected linebreaks to be LF but found CRLF linebreak-style 这就是eslint的报错了&#xff0c;可能是原作者…

目标检测自顶向下入门

最近在学习Yolo和OpenCV这些计算机视觉的相关领域&#xff0c;把深度学习啃了个大概&#xff0c;准备着手学习一下Yolov5&#xff0c;趁着这个机会入门一下目标检测这个领域&#xff0c;也算是自顶向下地学习一遍吧。 目标检测 什么是目标检测 物体识别&#xff08;Object de…

百川智能晋升200亿大模型独角兽

百川智能向创投日报记者确认&#xff0c;大模型创企百川智能已完成50亿元A轮融资&#xff1b;百川智能已成为国内第三家估值200亿元的大模型独角兽。 从包括百川智能在内的大模型创业企业的融资情况看&#xff0c;当前&#xff0c;选择出手大模型项目的资方出现从早期VC转向大…

如何穿透模糊,还原图片真实面貌

目录 图像清晰化的魔法棒&#xff1a;AI如何穿透模糊&#xff0c;还原图片真实面貌 前言 论文背景 论文思路 模型介绍 复现过程 演示视频 使用方式 本文所涉及所有资源均在传知代码平台可获取。 图像清晰化的魔法棒&#xff1a;AI如何穿透模糊&#xff0c;还原图片真实面貌 在我…

算法:[递归/搜索/回溯]二叉树的深搜

目录 题目一&#xff1a;计算布尔二叉树的值 题目二&#xff1a;求根节点到叶节点数字之和 题目三&#xff1a;二叉树剪枝 题目四&#xff1a;验证二叉搜索树 题目五&#xff1a;二叉搜索树中第k小的元素 题目六&#xff1a;二叉树的所有路径 题目一&#xff1a;计算布尔…

springboot整合 knife4j 接口文档

第一步&#xff1a;引入依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.4.0</version></dependency> 第二步&#xff1a;写入配置 方…

猫头虎分享 || 最全Python的Scapy库基础知识点汇总

&#x1f431;‍&#x1f464; 猫头虎分享 || Python的Scapy库基础知识点汇总 摘要 Scapy 是一个强大的Python库&#xff0c;用于网络数据包的生成、解析和操作。通过Scapy&#xff0c;开发者可以轻松地创建自定义数据包&#xff0c;捕获网络流量&#xff0c;并执行网络扫描。…

二叉树的链式结构和顺序结构的增删查改

树的概念 树是一种非线性的数据结构&#xff0c;它是一个n个节点组成的具有层次关系的集合&#xff0c;一棵树由一个根节点和若干个其余节点构成&#xff0c;除了根节点外&#xff0c;其他的节点都由一个前驱和多个后继&#xff0c;而根节点可以有多个后继&#xff0c;但没有前…

探索 Blockly:自定义积木实例

3.实例 3.1.基础块 无输入 , 无输出 3.1.1.json var textOneJson {"type": "sql_test_text_one","message0": " one ","colour": 30,"tooltip": 无输入 , 无输出 };javascriptGenerator.forBlock[sql_test_te…

没打印机怎么打印东西?

在日常生活中&#xff0c;我们经常会遇到需要打印文件的情况&#xff0c;无论是学习资料、工作文档&#xff0c;还是个人兴趣的资料收集。然而&#xff0c;并不是每个人家里都有打印机&#xff0c;或者打印机出现了故障。在这种情况下&#xff0c;寻找一个高效、经济的打印途径…