目录

  • 函数重载
  • 运算符重载
    • C++运算符重载范围对照表
      • 注意事项
    • 运算符重载语法
    • 全局运算符重载
    • 类内运算符重载
      • 下面以一个一元运算符为例,介绍特性1:
      • 下面介绍特性3:(必须类内重载的运算符‌)

函数重载

 函数重载是指同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同
函数重载的要点:

  1. 同一作用域的同名函数。
    也就是说,如果两个同名的函数不在同一个作用域那就不算重载,具体调用在哪个域就使用哪个函数。
  2. 形式参数,也就是传入的参数。个数、类型或者顺序必须不同,编译器会自动根据传入的参数判断使用的是哪个函数。
     下面举例体会:
#include<iostream>
using namespace std;namespace myspace{void myfunction(int){cout<<"Hello from myspace"<<endl;}void myfunction(double){cout<<"Hello from myspace double"<<endl;}
}void myfunction(float)
{cout<<"Hello from global namespace"<<endl;
}   int main()
{myspace::myfunction(10); //输出Hello from myspace,匹配到myspace::myfunction(int)myspace::myfunction(3.14); ///输出Hello from myspace double,匹配到myspace::myfunction(double)myfunction(1.23); //输出Hello from global namespace,匹配到myfunction(float)return 0;
}

运行后输出的结果如下:
在这里插入图片描述
两个在同一个命名空间的函数myfunction,根据其传入值的类型来决定实际调用哪个。并且当不同命名空间的myfunction调用时,总是选择最近的一个(全局)。符合预期的结果。

函数重载的好处显而易见,可以极大程度地避免冗余的函数命名,例如可以add_int和add_double之类的函数合并为一个同名的add,优化代码复用与维护‌。

运算符重载

 运算符重载最经典的一个例子就是iostream中的cin与cout重载的<<与>>。原本>> or <<只是用来作移位操作的,这里被重载为输入与输出的功能。
 运算符重载(Operator Overloading)是面向对象编程中的核心特性,允许对已有运算符赋予新的功能以适应自定义数据类型。其本质是通过定义特定函数,改变运算符在处理类或结构体时的行为逻辑,使得对象操作更贴近内置类型的使用方式。简单来说就是对已有的运算符进行函数重载,赋予新的功能可以重载的运算符有下面:

C++运算符重载范围对照表

运算符类型可重载运算符不可重载运算符
算术运算符+ - * / % ++ --
关系运算符== != < > <= >=
逻辑运算符&& || !
位运算符& | ^ ~ << >>
赋值运算符= += -= *= /= %= &= |= ^= <<= >>=
其他运算符[] () -> , new delete new[] delete[]:: .* . ?: sizeof typeid
特殊说明流运算符<< >>必须全局重载成员访问符.等禁止重载

注意事项

  1. 不能改变运算符优先级和结合性
  2. 至少一个操作数为自定义类型
  3. 保持运算符原有语义

运算符重载语法

 运算符重载有着严格的语法规定:

返回类型 operator运算符符号(参数列表) { // 实现运算符逻辑 }

 并且重载之后遵循原运算符的计算顺序,例如My_class operator+(My_class c1,My_class c2)调用时应该为My_class num3 = num1 + num2

全局运算符重载

 百分之九十以上的运算符重载都是在类内进行的,即使是在类外的全局运算符重载函数,其输入参数也必须包含一个类对象
例如 int operator+( int a, int b)这样是不允许的。因为C++标准明确规定:运算符重载至少有一个参数必须是类类型、枚举类型或对它们的引用,不能重载基本类型(如int)的运算符‌。
改成下面这样可以编译通过:(string是一个类)

#include<iostream>
#include<string>
using namespace std;void operator+(string a,  int b)
{cout << "hello" << endl;
}int main()
{string s = "h";int i = 10;s + i; //操作符重载return 0;
}

输出为:
在这里插入图片描述
 当然了,全局运算符重载的作用可不是像上面这样用来搞怪的。前面说到了,运算符重载的输入参数必须有一个是类类型,枚举类型或对它们的引用,对于类内运算符重载来说,类内运算符重载默认第一个参数(左参数)是类本身指针(this)因此其可以忽略传入第一个参数的声明。
 对于全局运算符重载来说全局运算符重载默认第一个参数(左参数)可以是任意类类型,枚举类型或对它们的引用,并且需显式声明所有操作数参数(也就是说全局重载时,operate不能省略第一个传入的参数。)流运算符的重载必须是全局运算符重载
 下面给正经示例:


// 全局重载+,混合内置类型和类类型
Vector operator*(const Vector& v, double scalar) {return Vector(v.x * scalar, v.y * scalar);
}
// 调用方式
Vector v1 = v * 2.5;  // 合法

友元函数与流运算


#include <iostream>
using namespace std;class Vector {
private:double x, y;
public:Vector(double x=0, double y=0) : x(x), y(y) {}// 声明友元全局运算符friend Vector operator+(const Vector& v1, const Vector& v2);friend ostream& operator<<(ostream& os, const Vector& v);
};// 实现友元运算符+
Vector operator+(const Vector& v1, const Vector& v2) {return Vector(v1.x + v2.x, v1.y + v2.y);
}// 实现友元流输出运算符
ostream& operator<<(ostream& os, const Vector& v) {return os << "(" << v.x << ", " << v.y << ")";
}int main() {Vector a(1, 2), b(3, 4);cout << "a + b = " << a + b << endl;return 0;
}

上面的全局运算符重载定义了两个友元函数:

  1. + 号的重载。
  2. 流运算符 <<的重载。

定义成友元函数是因为两个全局运算符重载函数不属于类的成员函数,但它们都要访问类的私有成员。因此需要在类内声明它们为类的友元函数。

类内运算符重载

 类内运算符重载有这么几个核心特性:

  1. 隐式调用this指针。类内重载的运算符函数默认以this作为左操作数(左操作数也必须是当前对象),因此二元运算符只需显式声明一个参数(右操作数)‌。例如operator+(this,b) == operator+(b),this被省略。
    理论上一元运算符,如++,--之类的类内重载都不需要显式声明形参,但有时候为了区分运算的顺序,例如a++和++a,需要传入伪参数。
  2. operator作为成员函数,可直接访问类的私有成员,无需友元声明‌。
  3. 必须为类内重载的运算符:=(赋值)、[](下标)、()(函数调用)、->(成员访问)‌。

下面以一个一元运算符为例,介绍特性1:

#include<iostream>
using namespace std;class Counter {
public:int count;Counter(int n=0) : count(n) {}// 前缀++(返回引用,避免拷贝)Counter& operator++() {++count;return *this;}// 后缀++(int参数区分)Counter operator++(int) {Counter temp = *this;++count;return temp;}
};int main()
{Counter c;cout << c.count << endl; // 0cout << ++c.count << endl; // 1cout << c.count++ << endl; // 1cout << c.count << endl; // 2return 0;
}

下面介绍特性3:(必须类内重载的运算符‌)

  1. 赋值运算符=‌
    用于对象间的深拷贝,需处理自赋值问题。
class MyClass {
public:MyClass& operator=(const MyClass& rhs);
};

正常来说,如果没有自定义赋值运算符编译器会默认进行浅拷贝,如下:

class BadClass {int* data;
public:BadClass() : data(new int[100]) {}~BadClass() { delete[] data; }
};
BadClass b1, b2;
b2 = b1;  // 危险:两个对象指向同一内存

什么是浅拷贝?
在C++中,当类包含动态分配的内存时,直接使用默认的赋值运算符会导致浅拷贝问题,前拷贝对于基本类型(如int、double)直接复制值,类类型成员调用其自身的赋值运算符,指针类型就仅复制地址(不复制指向的内容)

上面的代码进行浅拷贝后,对于b2.data的更改会同步到b1.data(浅拷贝使得二者地址相同)。更好的办法是下面这样:

class BadClass {int* data;
public:// ... 原有构造函数和析构函数 ...// 自定义赋值运算符BadClass& operator=(const BadClass& other) {if (this != &other) {  // 防止自赋值delete[] data;      // 释放原有内存data = new int[100]; //指向新地址std::copy(other.data, other.data + 100, data);  // 值深拷贝}return *this;}
};
  1. 函数调用运算符()仿函数
    仿函数就是让类的对象能像函数一样被调用。语法如下:
返回值类型 operator()(传入参数)

典型例子:


class Adder {int value;
public:Adder(int v) : value(v) {}int operator()(int x) { return x + value; }
};Adder add5(5);
cout << add5(10);  // 输出15

对于int operator()(int x) { return x + value; },类内运算符重载函数可以访问类内的成员变量,因此value无需传入。
3. 下标运算符[]‌
提供类似数组的访问方式,通常返回引用以支持修改。

class Vector {
public:int& operator[](int index);
};
  1. 成员访问运算符->‌
    常用于智能指针或迭代器实现。
class SmartPtr {
public:T* operator->() { return ptr; }
};

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

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

相关文章

七、SpringCloud 项目迁移至 K8s

七、SpringCloud 项目迁移至 K8s 文章目录 七、SpringCloud 项目迁移至 K8s1、环境准备1.1 集群规划1.2 SpringCloud 项目架构及迁移需求分析 2、迁移 Eureka 集群2.1 构建及容器化2.2 部署至 K8s2.3 创建通信Service 3、迁移网关服务3.1 构建及容器化3.2 部署至 K8s3.3 创建Se…

通过具有一致性嵌入的大语言模型实现端到端乳腺癌放射治疗计划制定|文献速递-最新论文分享

Title 题目 End-to-end breast cancer radiotherapy planning via LMMs with consistency embedding 通过具有一致性嵌入的大语言模型实现端到端乳腺癌放射治疗计划制定 01 文献速递介绍 近年来&#xff0c;受大型语言模型&#xff08;LLM&#xff09;启发的新一代人工智…

MCP Chart Server服务本地部署案例

一、MCP Chart Server介绍 MCP Chart Server是一个专业的图表生成服务&#xff0c;支持多种图表类型&#xff0c;适用于数据可视化和分析。 MCP Chart Server是一种用于生成和呈现图表的服务器端软件。它提供了一个简单而强大的方式&#xff0c;让开发人员和系统管理员可以轻…

复合型浪涌保护器五大核心技术重构电气防护体系

开篇&#xff1a;从传统防护到智能守护的技术跨越 在电气设备面临浪涌威胁的防护场景中&#xff0c;浪涌保护器&#xff08;SPD&#xff09;始终扮演着关键角色。面对传统SPD在漏电流、续流等方面的技术局限&#xff0c;行业领先企业通过技术整合开发出复合型SPD&#xff0c;以…

c# 详细分析Task.sleep和Thread.sleep 的区别、使用场景和应用示例

文章目录 Task.Delay vs Thread.Sleep 详细分析与使用场景核心区别详细分析Thread.SleepTask.Delay 性能考量综合示例高级用法组合延迟与超时实现指数退避重试 总结建议 Task.Delay vs Thread.Sleep 详细分析与使用场景 核心区别 Task.Delay 和 Thread.Sleep 都用于在代码中引…

Vue 3 中的 `h` 函数详解

h 函数是 Vue 3 中用于创建**虚拟 DOM 节点(VNode)**的核心函数&#xff0c;它是 Vue 渲染系统的基石。下面我将全面解释它的作用、用法和重要性。 1. h 函数的基本概念 h 是 createVNode 的简称&#xff0c;来源于"hyperscript"的缩写传统。它的主要作用是&#x…

SoapCore 全面介绍:在 .NET Core 中实现 SOAP 服务的现代解决方案

一、什么是 SoapCore&#xff1f; 在现代微服务和 REST API 成为主流的今天&#xff0c;SOAP&#xff08;Simple Object Access Protocol&#xff09;看似已经被边缘化&#xff0c;但在许多企业和政务系统中&#xff0c;SOAP 仍然是 重要的通信协议。特别是在金融、保险、医疗…

JDBC工具类和SQL 注入问题

在软件开发中&#xff0c;数据库安全与高效访问一直是关键课题。本文将围绕 SQL 注入问题的原理、解决方案&#xff0c;以及 JDBC 开发中的工具类演进和连接池技术展开探讨&#xff0c;结合实际代码示例&#xff0c;为开发者提供清晰的技术实践指南。 SQL 注入问题的核心原理与…

2022年SEVC SCI2区,分数阶蚁群算法FACA:一种基于分数阶长期记忆的合作学习方法,深度解析+性能实测

目录 1.摘要2.分数阶微积分基础知识3.分数阶蚁群算法FACA4.分数阶蚁群算法FACA数学证明与分析5.结果展示6.参考文献7.代码获取8.算法辅导应用定制读者交流 1.摘要 本文提出了一种新颖分数阶蚁群算法&#xff08;Fractional-Order Ant Colony Algorithm&#xff0c; FACA&#…

java+vue+SpringBoo数字科技风险报告管理系统(程序+数据库+报告+部署教程+答辩指导)

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿ppt部署教程代码讲解代码时间修改工具 技术实现 开发语言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot数据库&#xff1a;mysql 开发工具 JDK版本&#xff1a;JDK1.…

YOLOv12_ultralytics-8.3.145_2025_5_27部分代码阅读笔记-augment.py

augment.py ultralytics\data\augment.py 目录 augment.py 1.所需的库和模块 2.class BaseTransform: 3.class Compose: 4.class BaseMixTransform: 5.class CutMix(BaseMixTransform): 6.class CopyPaste(BaseMixTransform): 7.def v8_transforms(dataset, img…

跨芯片 AI 算子库 FlagGems 正式加入PyTorch 基金会生态项目体系

2025年北京智源大会 PyTorch Day China 论坛上&#xff0c;PyTorch 基金会执行董事 Matt White 宣布高性能通用 AI 算子库 FlagGems 项目获得批准&#xff0c;正式加入 PyTorch 生态项目体系。Pytorch基金会于6月26日在推特上进行了官方宣布。 作为唯一支持多种AI芯片架构的算…

vue + vue-router写登陆验证的同步方法和异步方法,及页面组件的分离和后端代码

先写一个用vue cdn写一个登陆验证的小示例后端代码 前端719.html <div id"app"><div id"loginForm">//路由层&#xff0c;登陆页和后台主页<router-link to"/">Login</router-link><router-link to"/home&quo…

.netcore 一个mvc到静态html实现

一、新建Mvc项目 Program.cs添加拦截 二、添加一个集成测试 将页面转为html到wwwroot下面 UnitGenHtml.cs using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.VisualStudio.TestPlatform.TestHost;namespace SaaS.OfficialWeb…

实现Taro小程序+nut-ui左滑删除效果

Taro小程序开发中&#xff0c;使用nut-ui组件&#xff0c;实现左滑删除卡片效果&#xff08;自定义删除按钮样式&#xff09; html代码部分 <nut-swipe class"carBox" v-for"(item, index) in carList" :key"item" :ref"(el) > se…

LLM 系列(五):模型训练篇

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…

Oracle LogMiner分析日志的三种方法示例

Oracle LogMiner分析日志的三种方法示例 方法一:Online Catalog作为日志挖掘字典自动获取日志模式手动获取日志模式方法二:Redo Log作为日志挖掘字典自动获取日志模式手动获取日志模式方法三:Flat File作为日志挖掘字典自动获取日志模式手动获取日志模式📖 Oracle LogMine…

Java 中 List.stream() 的全面使用指南(含完整示例)

标签&#xff1a;Java8, Stream API, 函数式编程, 集合操作 一、前言 随着 Java 8 的推出&#xff0c;Stream API 成为了处理集合数据的一种高效方式。List.stream() 是 Java Stream API 的入口方法之一&#xff0c;它允许开发者将集合转换为流&#xff0c;并通过链式调用实现…

香港 8C 站群服务器买来可以做哪些业务?

香港8C站群服务器&#xff08;即提供8个不同C段IP地址的服务器&#xff09;凭借多IP独立分配、低延迟网络及免备案优势&#xff0c;适用于以下关键业务场景&#xff1a; 一、SEO优化与搜索引擎运营 SEO站群搭建&#xff1a;为 80-100 个网站分配 8 个不同 C 段 IP &#xff0…

UI前端与数字孪生融合新趋势:智慧医疗的可视化诊断辅助

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 一、引言&#xff1a;数字孪生重塑智慧医疗诊断范式 在医疗数字化转型的浪潮中&#xff0c;数…