C++ 操作重载与类型转换

文章目录

    • 基本概念
      • 为什么使用操作重载?
      • 注意事项:
    • 输入和输出运算符
      • 重载输出运算符 `<<`
      • 重载输入运算符 `>>`
    • 算术和关系运算符
      • 算术运算符
      • 相等运算符
      • 关系运算符
    • 赋值运算符
      • 基本原则:
      • 示例:
      • 注意事项:
    • 下标运算符
      • 实现原则:
      • 示例:
      • 注意事项:
    • 递增和递减运算符
      • 两种形式:
      • 示例:
      • 注意事项:
    • 成员访问运算符
      • 点运算符 `.`
      • 箭头运算符 `->`
      • 示例:
      • 注意事项:
    • 函数调用运算符
      • Lambda是函数对象
      • 标准库定义的函数对象
      • 可调用对象与 `std::function`
      • 注意事项:
    • 重载、类型转换与运算符
      • 类型转换运算符
      • 避免有二义性的类型转换
      • 函数匹配与重载运算符
      • 注意事项:

基本概念

在C++中,操作重载(Operator Overloading)允许对已有的操作符赋予额外的含义,使得它们可以用于自定义的数据类型。比如,我们可以定义两个对象的加法操作。

类型转换是指将一个类型的实例转换为另一个类型。在C++中,类型转换可以是显式的或隐式的,而类型转换运算符允许控制这个转换过程。

为什么使用操作重载?

  • 可读性:使代码更易读,更接近自然语言。
  • 直观性:对象操作更直观、更符合对象的自然属性。
  • 重用性:在不同上下文中重用相同的符号,但有不同的实现。

注意事项:

  • 重载的操作符应该与原有操作符的语义相似。
  • 不能改变操作符的优先级。
  • 不能创建新的操作符。
  • 某些操作符,如 ::, .*, .?:,不能被重载。

输入和输出运算符

输入(>>)和输出(<<)运算符在C++中用于数据的输入和输出。通常情况下,这些操作符被用于标准的输入输出流(如 std::cinstd::cout)。但是,也可以重载这些运算符以使它们适用于自定义的数据类型。

重载输出运算符 <<

为了使自定义类型能够通过 std::cout 输出,需要重载 << 运算符。这通常通过编写一个非成员函数来实现,该函数接受一个输出流(如 std::ostream)和要输出的对象作为参数。

示例

class MyClass {
public:int value;MyClass(int v) : value(v) {}
};std::ostream& operator<<(std::ostream& os, const MyClass& obj) {os << obj.value;return os;
}

在这个例子中,使用 std::cout << myObject; 时,就会调用我们为 MyClass 类型重载的 << 运算符。

重载输入运算符 >>

类似地,为了使自定义类型可以从 std::cin 或其他输入流中接收输入,需要重载 >> 运算符。这也是通过编写一个非成员函数来实现的。

示例

std::istream& operator>>(std::istream& is, MyClass& obj) {is >> obj.value;return is;
}

通过这种方式,可以使用 std::cin >> myObject; 来给 MyClass 类型的对象输入值。

算术和关系运算符

在C++中,不仅可以重载输入输出运算符,还可以重载各种算术和关系运算符,以便在自定义数据类型上实现特定的操作。

算术运算符

算术运算符包括 +, -, *, /, % 等。通过重载这些运算符,可以定义自定义类型对象间的加法、减法、乘法等操作。

示例

class Complex {
public:double real;double imag;Complex(double r, double i) : real(r), imag(i) {}// 重载加法运算符Complex operator+(const Complex& rhs) const {return Complex(real + rhs.real, imag + rhs.imag);}// 其他运算符...
};

在这个例子中,定义了一个复数类 Complex 并重载了 + 运算符,使其能够实现两个复数的加法。

相等运算符

相等运算符(==)和不等运算符(!=)用于比较两个对象是否相等或不等。重载这些运算符时,通常需要确保它们的行为符合逻辑和直觉。

示例

class MyClass {
public:int value;MyClass(int v) : value(v) {}bool operator==(const MyClass& rhs) const {return value == rhs.value;}bool operator!=(const MyClass& rhs) const {return !(*this == rhs);}
};

在这个例子中,MyClass 类型的对象通过比较它们的 value 成员来判断是否相等。

关系运算符

关系运算符包括 <, >, <=, >= 等。它们用于定义对象间的大小比较逻辑。

示例

bool operator<(const MyClass& lhs, const MyClass& rhs) {return lhs.value < rhs.value;
}
// 其他关系运算符...

在这个例子中,< 运算符被重载以比较两个 MyClass 类型对象的 value

赋值运算符

赋值运算符(=)是C++中非常重要的一个运算符,它用于将一个对象的值赋给另一个对象。对于自定义的数据类型,通常需要重载赋值运算符,以确保对象之间的赋值行为正确。

基本原则:

  • 自赋值安全:确保对象自赋值时不会出现问题。
  • 返回引用:通常赋值运算符返回一个指向其左侧操作数的引用。
  • 释放资源:在覆盖旧值之前,释放对象当前占用的资源。

示例:

class MyClass {
public:int* data;MyClass(int d) : data(new int(d)) {}~MyClass() { delete data; }// 重载赋值运算符MyClass& operator=(const MyClass& rhs) {if (this != &rhs) { // 自赋值检查delete data; // 释放现有资源data = new int(*rhs.data); // 分配新资源}return *this;}
};

在这个例子中,定义了一个类 MyClass,它有一个动态分配的整数成员。赋值运算符首先检查自赋值,然后释放当前对象所持有的资源,并从右侧操作数复制数据。

注意事项:

  • 在处理动态资源或复杂的内部结构时,正确重载赋值运算符尤为重要。
  • 必须考虑异常安全性和资源泄露的问题。

下标运算符

下标运算符([])在C++中用于访问对象中的元素,如数组或容器类的元素。对于自定义数据类型,可以重载下标运算符,以提供类似数组一样的访问方式。

实现原则:

  • 直观性:确保下标运算符的使用和普通数组或标准库容器的使用方式一致。
  • 支持常量和非常量版本:通常需要提供两个版本的下标运算符——一个用于常量对象,一个用于非常量对象。

示例:

class MyArray {int* array;int size;
public:MyArray(int sz) : size(sz), array(new int[sz]) {}~MyArray() { delete[] array; }// 非常量版本int& operator[](int index) {return array[index];}// 常量版本const int& operator[](int index) const {return array[index];}
};

在这个例子中,MyArray 类重载了下标运算符,允许用户通过索引访问数组元素,就像使用普通数组一样。

注意事项:

  • 通常需要对索引值进行范围检查,以避免越界错误。
  • 下标运算符应该快速且高效。

递增和递减运算符

递增(++)和递减(--)运算符在C++中用于增加或减少对象的值。这些运算符可以被重载以适用于自定义数据类型,允许对象以特定方式响应递增或递减操作。

两种形式:

  • 前缀版本++obj--obj,先改变对象的值,然后返回改变后的对象。
  • 后缀版本obj++obj--,先返回对象当前的值,然后改变对象的值。

示例:

class Counter {
private:int value;
public:Counter(int v = 0) : value(v) {}// 前缀递增Counter& operator++() {++value;return *this;}// 后缀递增Counter operator++(int) {Counter temp = *this;++(*this);return temp;}// 类似地,可以实现递减运算符
};

在这个例子中,Counter 类重载了递增运算符。前缀版本直接增加值并返回,而后缀版本则首先创建一个当前状态的副本,然后增加值,最后返回副本。

注意事项:

  • 后缀版本通常需要返回对象的副本,这可能涉及额外的开销。
  • 适当重载递增和递减运算符可以提高代码的可读性和直观性。

成员访问运算符

在C++中,成员访问运算符包括两种:点运算符(.)和箭头运算符(->)。点运算符用于访问对象的成员,而箭头运算符用于通过指针访问对象的成员。对于自定义数据类型,尤其是实现了指针类行为的类型,可以重载箭头运算符。

点运算符 .

点运算符用于直接访问对象的成员。这个运算符不能被重载,因为它总是需要直接访问对象的实际成员。

箭头运算符 ->

箭头运算符用于通过对象的指针来访问其成员。如果我们创建了类似指针的对象,比如智能指针,就需要重载这个运算符。

示例:

template <typename T>
class SmartPointer {
private:T* ptr;
public:SmartPointer(T* p = nullptr) : ptr(p) {}~SmartPointer() { delete ptr; }T& operator*() { return *ptr; }T* operator->() { return ptr; }
};

在这个例子中,定义了一个简单的智能指针类 SmartPointer。通过重载 -> 运算符,可以通过智能指针访问其指向对象的成员,就像使用普通指针一样。

注意事项:

  • 重载的 -> 运算符必须返回一个对象的指针,或者是另一个定义了 -> 操作的对象。
  • 这种重载通常用于实现智能指针、迭代器等类似指针的对象。

函数调用运算符

函数调用运算符 () 在C++中可以被重载,使得一个对象能像函数一样被调用。这种特性主要用于创建可调用的对象,例如函数对象(functors)或者Lambda表达式。

Lambda是函数对象

Lambda表达式是C++11引入的一个特性,它允许我们定义匿名函数对象。Lambda可以捕获作用域中的变量,并且可以像普通函数一样被调用。

示例

auto sum = [](int a, int b) { return a + b; };
std::cout << sum(3, 4); // 输出 7

在这个例子中,我们定义了一个Lambda表达式来求两个数的和。

标准库定义的函数对象

标准库中提供了许多预定义的函数对象,如 std::plusstd::minus 等,这些都是重载了函数调用运算符的类。

示例

std::plus<int> add;
std::cout << add(3, 4); // 输出 7

在这个例子中,我们使用了标准库中的 std::plus 类来进行加法操作。

可调用对象与 std::function

std::function 是一个模板类,它可以包裹任何可调用对象,比如普通函数、Lambda表达式、函数对象等。

示例

std::function<int(int, int)> add = [](int a, int b) { return a + b; };
std::cout << add(3, 4); // 输出 7

在这个例子中,使用 std::function 来存储一个Lambda表达式。

注意事项:

  • 通过重载函数调用运算符,可以让对象行为类似于函数。
  • Lambda表达式和 std::function 提供了灵活的方式来处理可调用对象。

重载、类型转换与运算符

在C++中,除了重载常用的算术和逻辑运算符外,还可以重载类型转换运算符。这使得我们可以定义对象如何从一种类型转换为另一种类型。

类型转换运算符

类型转换运算符用于将一个对象隐式或显式地转换为另一种类型。这些运算符的重载可以提供更多的控制,确保类型转换按预期进行。

示例

class MyClass {int value;
public:MyClass(int v) : value(v) {}// 转换为int类型的运算符operator int() const {return value;}
};

在这个例子中,MyClass 对象可以隐式地转换为 int 类型。

避免有二义性的类型转换

类型转换应该明确无误。如果一个类提供了多个可能的类型转换,可能会导致二义性,这应该尽量避免。

函数匹配与重载运算符

在重载运算符时,应该注意函数匹配的问题。重载应该清晰而明确,不应该引起调用者的困惑或误解。

注意事项:

  • 类型转换运算符应该谨慎使用,以避免引入错误或二义性。
  • 显式关键字(explicit)可以用来防止隐式类型转换,确保转换行为明确。
  • 重载运算符应该保持一致性和直观性,避免过度使用导致代码难以理解。

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

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

相关文章

outlook邮件群发单显技巧?群发怎么单显?

outlook邮件群发单显如何设置&#xff1f;QQ邮箱怎么群发单显&#xff1f; 在群发邮件时&#xff0c;如何让每个收件人只看到自己的名字&#xff0c;而不是其他人的名字&#xff0c;这就涉及到所谓的“单显”技巧。下面蜂邮EDM就为大家揭秘Outlook邮件群发单显的奥秘。 outlo…

实战干货:用 Python 批量下载百度图片!

为了做一个图像分类的小项目&#xff0c;需要制作自己的数据集。要想制作数据集&#xff0c;就得从网上下载大量的图片&#xff0c;再统一处理。 这时&#xff0c;一张张的保存下载&#xff0c;就显得很繁琐。那么&#xff0c;有没有一种方法可以把搜索到的图片直接下载到本地电…

Spark 运行架构

Spark 框架的核心是一个计算引擎&#xff0c;整体来说&#xff0c;它采用了标准 master-slave 的结构。 如下图所示&#xff0c;它展示了一个 Spark 执行时的基本结构。图形中的 Driver 表示 master&#xff0c; 负责管理整个集群中的作业任务调度。图形中的 Executor 则是 sla…

Swift爬虫使用代理IP采集唯品会商品详情

目录 一、准备工作 二、代理IP的选择与使用 三、使用Swift编写唯品会商品爬虫 四、数据解析与处理 五、注意事项与优化建议 六、总结 一、准备工作 在开始编写爬虫之前&#xff0c;需要准备一些工具和库&#xff0c;以确保数据抓取的顺利进行。以下是所需的工具和库&…

速盾高防ip:专业防御ddos

速盾高防IP是速盾网络为企业提供的专业DDoS攻击防御解决方案之一。作为一种先进的网络安全服务&#xff0c;速盾高防IP致力于保护客户的网络资源免受分布式拒绝服务&#xff08;DDoS&#xff09;攻击的威胁。以下是速盾高防IP的一些关键特点和优势&#xff1a; 实时攻击监测&am…

Mac 软件出现「意外退出」及「打不开」解决方法

Mac 软件出现「意外退出」及「打不开」解决方法 软件出现意外退出及软件损坏的情况&#xff0c;这是因为苹果删除了TNT的证书&#xff0c;所以大部分TNT破解的Mac软件会出现无法打开&#xff0c;提示意外退出。 终端需先安装Xcode或Apple命令行工具 如未装Xcode可以使用下列命…

【算法设计与分析】分治-时间复杂度计算

目录 主定理 Master Theorem分治算法运行时间的递归表示主定理的简化形式 主定理的一般形式 递归树 Recursion Tree递归树的简单结论 主定理 Master Theorem 分治算法运行时间的递归表示 将原问题分解成 a 个子问题递归求解&#xff0c;每个子问题的规模是原问题的 1/b。同时子…

go-cqhttp作者停止维护——替代品OpenShamrock的使用方法

目录 前言 解决办法 配置要求 实操 刷入面具 安装lsp框架 安装OpenShamrock和QQ 注意 大功告成 前言 由于QQ官方针对协议库的围追堵截&#xff0c;go-cqhttp已经无力维护下去了 原文连接 QQ Bot的未来以及迁移建议 Issue #2471 Mrs4s/go-cqhttp (github.com)https…

libcurl的get、post的使用

demo使用的是curl-8.3.0.tar.gz&#xff0c;其它版本也可以&#xff0c;安装教程可以去网上搜 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h> /* somewhat unix-specific */ #include &…

最新GPT4.0使用教程,AI绘画,ChatFile文档对话总结+GPT语音对话使用,DALL-E3文生图

一、前言 ChatGPT3.5、GPT4.0、GPT语音对话、Midjourney绘画&#xff0c;文档对话总结DALL-E3文生图&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和…

16.顺子日期(14)

题目 public class Main {public static boolean isLegal(String date) {int l 0;int n date.length();while(l<(n-3)) {int t1 (int)Integer.valueOf(date.substring(l,l1));int t2 (int)Integer.valueOf(date.substring(l1,l2));int t3 (int)Integer.valueOf(date.s…

FreeRTOS 实时操作系统第十二讲 - 计数信号量

一、信号量的概念 1、信号量的基本概念 消息队列是实现任务与任务或任务与中断间通信的数据结构&#xff0c;可类比裸机编程中的数组 信号量是实现任务与任务或任务与中断间通信的机制&#xff0c;可以类比裸机编程中的标志位 信号量 (semaphore) 可以实现任务与任务或任务与中…

C#的StringBuilder属性

目录 一、StringBuilder构造器 二、StringBuilder属性 1.StringBuilder.Capacity 属性 2.StringBuilder.Chars[Int32] 属性 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;实例 3.StringBuilder.Length 属性 &#xff08;1&#xff09;定义 &#xff08;2&…

银河麒麟Kylin-Server-V10-SP3使用ISO镜像搭建本地内网YUM/DNF源cdrom/http

机房服务器安装一般是内网环境&#xff0c;需要配置本地的YUM/DNF源。本文介绍通过ISO镜像搭建内网环境的UM/DNF源 准备工作&#xff1a; 提前准备好Kylin-Server-V10-SP3的ISO镜像文件。 本机IP地址&#xff1a;192.168.40.201 镜像存放目录/data/iso/Kylin-Server-V10-SP3-Ge…

Linux-端口、nmap命令、netstat命令

端口是设备与外界通讯交流的出入口&#xff0c;可分为物理端口和虚拟端口 物理端口实际存在可以看见&#xff0c;而虚拟端口是指计算机内部的端口&#xff0c;是不可见的&#xff0c;用来操作系统和外部交互使用。 IP地址不能锁定程序&#xff0c;所以可以通过端口&#xff0…

原生微信小程序如何动态修改svg图片颜色及尺寸、宽高(封装svgIcon组件)解决ios不显示问题

最终效果 前言 动态设置Svg图片颜色就是修改Svg源码的path中的fill属性&#xff0c; 通过wx.getFileSystemManager().readFile读取.xlsx文件 ios不显示需要把encoding设置 binary 把文件转成base64 封装svg-icon组件 1、在项目的components下新建svg-icon文件夹&#xff0c;新…

OA系统与工单系统的区别:功能、应用与优势对比

很多企业在选购系统的时候会陷入选择困难症的漩涡。市面上的各种系统&#xff0c;比如ERP系统、OA系统、工单系统等等让人眼花缭乱。想要选择一款合适的系统&#xff0c;前提是明确地知道自己需要用它来做什么&#xff0c;其次去了解每个系统的应用场景、功能等是否与自己的需求…

自动驾驶感知-预测-决策-规划-控制学习(3):感知方向文献阅读笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、文章主题二、摘要阅读1.名词理解①点云是什么&#xff1f;②二维图像分割器③轻量化卷积网络提取特征④单模态表达和多模态特征融合的区别⑤基于ROS的多传感…

jetson deepstream 解码接入编码输出

不需要编解码输出画面的直接到7 使用就行 1 jetson主板编译工具 在jetson主板上安装gstreamer工具链&#xff0c;编译opencv sudo apt install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-ugly gstreamer1.0-rtsp python3-dev pytho…

安全与认证Week3 Tutorial+历年题补充

目录 1) 什么是重放攻击? 2)什么是Kerberos系统?它提供什么安全服务? 3)服务器验证客户端身份的一种简单方法是要求提供密码。在Kerberos中不使用这种身份验证&#xff0c;为什么?Kerberos如何对服务器和客户机进行身份验证? 4) Kerberos的四个要求是什么?Kerberos系…