C++之operator

1、operator

        operator是C++关键字之一, 称为重载运算符(也称“重载操作符”)所谓重载,就是赋予新的含义。函数重载(Function Overloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作。运算符重载(Operator Overloading)也是一个道理,同一个运算符可以有不同的功能

        例如,+号可以对不同类型(int、float 等)的数据进行加法操作;<<既是位移运算符,又可以配合cout向控制台输出数据。C++本身已经对这些运算符进行了重载。C++也允许程序员自己重载运算符,这给我们带来了很大的便利。

实现运算符重载的方式通常有以下两种:

        (1)运算符重载实现为类的成员函数;

        (2)运算符重载实现为非类的成员函数(即全局函数)。

2、重载为类的成员函数(以“==”举例)

        在类体中声明(定义)需要重载的运算符,声明方式跟普通的成员函数一样,只不过运算符重载函数的名字是【operator紧跟一个C++预定义的操作符】【以“==”为例,函数名就是“operator==”

(1)在类中实现函数的逻辑:


#include <iostream>
using namespace std;

class student
{
private:
    char name[10];
    int age;
public:
    student(int nAge)  // 构造函数,对私有变量赋值
    {
        this->age = nAge;
    }

    bool operator==(const student& ps)   // 重载了“==”运算符,用于判断两个值是否相等
    {
        if (this->age == ps.age)
            return true;
        return false;
    }
};

int main()
{
    student p1(10);
    student p2(10);

    if (p1 == p2)
        cout << "p1 is equal with p2." << endl;
    else
        cout << "p1 is not equal with p2." << endl;
    return 0;
}

输出:

p1 is equal with p2.

(2)在类外实现函数的逻辑:


#include <iostream>
using namespace std;

class student
{
private:
    char name[10];
    int age;
public:
    student(int nAge)  // 构造函数,对私有变量赋值
    {
        this->age = nAge;
    }

    bool operator==(const student& ps);   // 重载了“==”运算符,用于判断两个值是否相等
};

bool student::operator==(const student& ps)
{
    if (this->age == ps.age)
        return true;
    return false;
}

int main()
{
    student p1(10);
    student p2(10);

    if (p1 == p2)
        cout << "p1 is equal with p2." << endl;
    else
        cout << "p1 is not equal with p2." << endl;
    return 0;
}

输出:

p1 is equal with p2.

3、重载为全局函数(以“==”举例)

        对于全局重载运算符,代表左操作数的参数必须被显式指定。

#include <iostream>
using namespace std;

class student
{
public:
    char name[10];
    int age;
};

// 左操作数的类型必须被显式指定;此处指定的类型为person类
bool operator==(student const& p1, student const& p2)
{
    if (p1.age == p2.age)
        return true;
    else
        return false;
}

int main()
{
    student p1;
    student p2;
    p1.age = 18;
    p2.age = 18;

    if (p1 == p2)
        cout << "p1 is equal with p2." << endl;
    else
        cout << "p1 is NOT equal with p2." << endl;
    return 0;
}

输出:

p1 is equal with p2.

4、重载“数学运算符”

        四则运算符(+、-、*、/、+=、-=、*=、/=)和关系运算符(>、<、<=、>=、==、!=)都是数学运算符,它们在实际开发中非常常见,被重载的几率也很高,并且有着相似的重载格式。本文以复数类 Complex 为例对它们进行重载,重在演示运算符重载的语法以及规范。

        复数能够进行完整的四则运算,但不能进行完整的关系运算:我们只能判断两个复数是否相等,但不能比较它们的大小,所以不能对 >、<、<=、>= 进行重载

#include <iostream>
#include <cmath>
using namespace std;

//复数类
class Complex {
public:
    //构造函数
    Complex(double real = 0.0, double imag = 0.0) : m_real(real), m_imag(imag) { }
public:
    //运算符重载
    //以全局函数的形式重载
    friend Complex operator+(const Complex& c1, const Complex& c2);
    friend Complex operator-(const Complex& c1, const Complex& c2);
    friend Complex operator*(const Complex& c1, const Complex& c2);
    friend Complex operator/(const Complex& c1, const Complex& c2);
    friend bool operator==(const Complex& c1, const Complex& c2);
    friend bool operator!=(const Complex& c1, const Complex& c2);

    //以成员函数的形式重载
    Complex& operator+=(const Complex& c);
    Complex& operator-=(const Complex& c);
    Complex& operator*=(const Complex& c);
    Complex& operator/=(const Complex& c);
public:
    //成员函数
    double real() const { return m_real; }
    double imag() const { return m_imag; }
private:
    double m_real;  //实部
    double m_imag;  //虚部
};

//重载为全局函数
//重载+运算符
Complex operator+(const Complex& c1, const Complex& c2) {
    Complex c;
    c.m_real = c1.m_real + c2.m_real;
    c.m_imag = c1.m_imag + c2.m_imag;
    return c;
}
//重载-运算符
Complex operator-(const Complex& c1, const Complex& c2) {
    Complex c;
    c.m_real = c1.m_real - c2.m_real;
    c.m_imag = c1.m_imag - c2.m_imag;
    return c;
}
//重载*运算符  (a+bi) * (c+di) = (ac-bd) + (bc+ad)i
Complex operator*(const Complex& c1, const Complex& c2) {
    Complex c;
    c.m_real = c1.m_real * c2.m_real - c1.m_imag * c2.m_imag;
    c.m_imag = c1.m_imag * c2.m_real + c1.m_real * c2.m_imag;
    return c;
}
//重载/运算符  (a+bi) / (c+di) = [(ac+bd) / (c²+d²)] + [(bc-ad) / (c²+d²)]i
Complex operator/(const Complex& c1, const Complex& c2) {
    Complex c;
    c.m_real = (c1.m_real * c2.m_real + c1.m_imag * c2.m_imag) / (pow(c2.m_real, 2) + pow(c2.m_imag, 2));
    c.m_imag = (c1.m_imag * c2.m_real - c1.m_real * c2.m_imag) / (pow(c2.m_real, 2) + pow(c2.m_imag, 2));
    return c;
}
//重载==运算符
bool operator==(const Complex& c1, const Complex& c2) {
    if (c1.m_real == c2.m_real && c1.m_imag == c2.m_imag) {
        return true;
    }
    else {
        return false;
    }
}
//重载!=运算符
bool operator!=(const Complex& c1, const Complex& c2) {
    if (c1.m_real != c2.m_real || c1.m_imag != c2.m_imag) {
        return true;
    }
    else {
        return false;
    }
}

//重载为成员函数
//重载+=运算符
Complex& Complex::operator+=(const Complex& c) {
    this->m_real += c.m_real;
    this->m_imag += c.m_imag;
    return *this;
}
//重载-=运算符
Complex& Complex::operator-=(const Complex& c) {
    this->m_real -= c.m_real;
    this->m_imag -= c.m_imag;
    return *this;
}
//重载*=运算符
Complex& Complex::operator*=(const Complex& c) {
    this->m_real = this->m_real * c.m_real - this->m_imag * c.m_imag;
    this->m_imag = this->m_imag * c.m_real + this->m_real * c.m_imag;
    return *this;
}
//重载/=运算符
Complex& Complex::operator/=(const Complex& c) {
    this->m_real = (this->m_real * c.m_real + this->m_imag * c.m_imag) / (pow(c.m_real, 2) + pow(c.m_imag, 2));
    this->m_imag = (this->m_imag * c.m_real - this->m_real * c.m_imag) / (pow(c.m_real, 2) + pow(c.m_imag, 2));
    return *this;
}

int main() {
    Complex c1(25, 35);
    Complex c2(10, 20);
    Complex c3(1, 2);
    Complex c4(4, 9);
    Complex c5(34, 6);
    Complex c6(80, 90);

    Complex c7 = c1 + c2;
    Complex c8 = c1 - c2;
    Complex c9 = c1 * c2;
    Complex c10 = c1 / c2;
    cout << "c7 = " << c7.real() << " + " << c7.imag() << "i" << endl;
    cout << "c8 = " << c8.real() << " + " << c8.imag() << "i" << endl;
    cout << "c9 = " << c9.real() << " + " << c9.imag() << "i" << endl;
    cout << "c10 = " << c10.real() << " + " << c10.imag() << "i" << endl;

    c3 += c1;
    c4 -= c2;
    c5 *= c2;
    c6 /= c2;
    cout << "c3 = " << c3.real() << " + " << c3.imag() << "i" << endl;
    cout << "c4 = " << c4.real() << " + " << c4.imag() << "i" << endl;
    cout << "c5 = " << c5.real() << " + " << c5.imag() << "i" << endl;
    cout << "c6 = " << c6.real() << " + " << c6.imag() << "i" << endl;

    if (c1 == c2) {
        cout << "c1 == c2" << endl;
    }
    if (c1 != c2) {
        cout << "c1 != c2" << endl;
    }

    return 0;
}

输出:

c7 = 35 + 55i
c8 = 15 + 15i
c9 = -450 + 850i
c10 = 1.9 + -0.3i
c3 = 26 + 37i
c4 = -6 + -11i
c5 = 220 + 4460i
c6 = 5.2 + 1.592i
c1 != c2

5、重载“>>”和“<<”

        在C++中,标准库本身已经对左移运算符“<<”和右移运算符“>>”分别进行了重载,使其能够用于不同数据的输入输出,但是输入输出的对象只能是C++内置的数据类型(例如 bool、int、double 等)和标准库所包含的类类型(例如 string、complex、ofstream、ifstream 等)。

        如果我们自己定义了一种新的数据类型,需要用输入输出运算符去处理,那么就必须对它们进行重载。本节以前面的complex类为例来演示输入输出运算符的重载。

        本节要达到的目标是让复数的输入输出和int、float等基本类型一样简单。假设num1、num2是复数,那么输出形式就是:

        cout<<num1<<num2<<endl;

输入形式就是:

        cin>>num1>>num2;

        cout是ostream类的对象,cin是istream类的对象,要想达到这个目标,就必须以全局函数(友元函数)的形式重载“<<”和“>>”。

#include <iostream>
using namespace std;

class complex {
public:
    complex(double real = 0.0, double imag = 0.0) : m_real(real), m_imag(imag) { };
public:
    friend complex operator+(const complex& A, const complex& B);
    friend complex operator-(const complex& A, const complex& B);
    friend complex operator*(const complex& A, const complex& B);
    friend complex operator/(const complex& A, const complex& B);
    //重载输入输出运算符
    friend istream& operator>>(istream& in, complex& A);
    friend ostream& operator<<(ostream& out, complex& A);
private:
    double m_real;  //实部
    double m_imag;  //虚部
};

//重载加法运算符
complex operator+(const complex& A, const complex& B) {
    complex C;
    C.m_real = A.m_real + B.m_real;
    C.m_imag = A.m_imag + B.m_imag;
    return C;
}

//重载减法运算符
complex operator-(const complex& A, const complex& B) {
    complex C;
    C.m_real = A.m_real - B.m_real;
    C.m_imag = A.m_imag - B.m_imag;
    return C;
}

//重载乘法运算符
complex operator*(const complex& A, const complex& B) {
    complex C;
    C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
    C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
    return C;
}

//重载除法运算符
complex operator/(const complex& A, const complex& B) {
    complex C;
    double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
    C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag) / square;
    C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag) / square;
    return C;
}

//重载输入运算符
istream& operator>>(istream& in, complex& A) {
    in >> A.m_real >> A.m_imag;
    return in;
}

//重载输出运算符
ostream& operator<<(ostream& out, complex& A) {
    out << A.m_real << " + " << A.m_imag << " i ";;
    return out;
}

int main() {
    complex c1, c2, c3;
    cin >> c1 >> c2;

    c3 = c1 + c2;
    cout << "c1 + c2 = " << c3 << 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;

    return 0;
}

输出:

1.2 3.4
56.4 7.8
c1 + c2 = 57.6 + 11.2 i
c1 - c2 = -55.2 + -4.4 i
c1 * c2 = 41.16 + 201.12 i
c1 / c2 = 7.24615 + 14.0308 i

6、其他重载

7、参考

        参考案例过多,暂不进行列举。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电商核心技术揭秘四十五:营销与广告策略(下)

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商技术揭秘四十一&#xff1a;电商平台的营销系统浅析 电商技术揭秘四十二&#…

苹果可能将OpenAI技术集成至iOS/iPadOS 18

&#x1f989; AI新闻 &#x1f680; 苹果可能将OpenAI技术集成至iOS/iPadOS 18 摘要&#xff1a;苹果正在与OpenAI就将GPT技术部署在iOS/iPadOS 18中进行谈判。这项技术被视为可能增强的Siri功能&#xff0c;即“AI聊天机器人”。除Siri外&#xff0c;新技术还可能改善Spotl…

mac idea 下载spring 源码遇到的问题

一、Kotlin: warnings found and -Werror specified 这个问题网上看了很多文章多说是缺少cglib、objenesis包。然后执行了 实际还是没有什么用 解决&#xff1a; 最后自己看了一下前面一个警告。说的就是版本太低。所以我觉得是这个前置问题导致的 然后搜索了改这个Kotlin版本…

在Mac上恢复已删除文件夹的最佳方法

“嗨&#xff0c;我从我的Mac Documents文件夹中删除了很多文件夹。已删除的文件夹包含我的重要文档和文件&#xff0c;是否可以取回它们&#xff1f;垃圾桶已被清洁软件清空。如何在我的Mac上恢复已删除的文件夹&#xff1f; 当您在 Mac 上删除 1 或 2 个文件夹时&#xff0c…

免费开源语音克隆-GPT-SoVITS-WebUI只需 5 秒的声音样本

语音克隆-GPT-SoVITS-WebUI 强大的少样本语音转换与语音合成Web用户界面。 功能&#xff1a; 零样本文本到语音&#xff08;TTS&#xff09;&#xff1a; 输入 5 秒的声音样本&#xff0c;即刻体验文本到语音转换。 少样本 TTS&#xff1a; 仅需 1 分钟的训练数据即可微调模型…

抖音小店运营实战班,全新升级 从零到进阶精通 分享月销百万小店核心秘密

课程内容&#xff1a; 1 2024抖音电商发展趋势及抖店运营策略(直播2024 0412).mp4 2 1-1抖音小店入驻流程(直播2024 04 12),mp4 3 1-2个体店铺VS企业店铺有什么区别(直播20240412).mp4 4 1-3抖音小店店铺搭建(直播2024 04 12).mp4 5 2-1-如何避免违禁词(附违禁词大全)(直播…

设计模式之模板模式

模板模式&#xff08;Template Method Pattern&#xff09;是行为设计模式之一&#xff0c;它定义了一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤&#xff0c;从而达到复用算法框架…

每日一题(力扣213):打家劫舍2--dp+分治

与打家劫舍1不同的是它最后一个和第一个会相邻&#xff0c;事实上&#xff0c;从结果思考&#xff0c;最后只会有三种&#xff1a;1 第一家不被抢 最后一家被抢 2 第一家被抢 最后一家不被抢 3 第一和最后一家都不被抢 。那么&#xff0c;根据打家劫舍1中的算法 我们能算出在i…

蓝桥杯练习系统(算法训练)ALGO-951 预备爷的悲剧

资源限制 内存限制&#xff1a;512.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 英语预备爷gzp是个逗(tu)比(hao)&#xff0c;为了在即将到来的英语的quiz中不挂科&#xff0c;gzp废寝忘食复习英语附录单词…

PAT (Advanced Level) - 1006 Sign In and Sign Out

模拟 #include <iostream> #include <cstring> #include <algorithm> using namespace std;int m; string open_id, open_time; string close_id, close_time;int main(){cin >> m;for (int i 0; i < m; i ) {string id, in_time, out_time;cin …

深度学习:基于Keras,使用长短期记忆人工神经网络模型(LSTM)对股票市场进行预测分析

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

Unity开发一个FPS游戏之四

在前面的系列中&#xff0c;我已介绍了如何实现一个基本的FPS游戏&#xff0c;这里将继续进行完善&#xff0c;主要是增加更换武器以及更多动作动画的功能。 之前我是采用了网上一个免费的3D模型来构建角色&#xff0c;这个模型自带了一把AR自动步枪&#xff0c;并且自带了一些…

链表经典面试题上

目录 创作不易&#xff0c;如若对您有帮助&#xff0c;还望三连&#xff0c;谢谢&#xff01;&#xff01;&#xff01; 题目一&#xff1a;203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 题目二&#xff1a;206. 反转链表 - 力扣&#xff08;LeetCode&#xff…

电脑如何查看一段时间内是否被人使用过?

前言 有时候我们可能会担心别人未经许可使用我们的电脑。为了确保自己不在场时电脑是否被使用过&#xff0c;以下两种方法可能会帮到你 第一种方法 WinX打开事件查看器。像WinX能快速打开很多东西&#xff0c;比如安装的应用(可以进行软件的删除)&#xff0c;设备管理器&…

网络性能测试工具iperf3 和iperf

目录 1. iperf工具介绍 2. 下载安装 3. 使用方法 1. iperf工具介绍 iperf 是一个网络性能测试工具&#xff0c;用于测量网络带宽和性能。它可以在客户端和服务器之间进行数据传输&#xff0c;并提供了丰富的选项来配置测试参数和输出格式。 iperf 和 iperf3 都是用于测量网…

什么是发售?

什么是发售? 很多人不知道什么是发售,因为这个词刚被广而告之,在这里普及一下什么是发售? 发售,它是通过一套流程,把你的产品疯狂大卖的一种技术。通常有三个步骤,就是造势、预售、发售。那么这三个词怎么理解呢? 第一步:造势 造势的核心是引发关注,但是不做销售…

【机器视觉】Segment Anything模型(SAM) C# 推理

Facebook开源的Segment Anything是一个基于大型预训练模型的计算机视觉工具&#xff0c;它使用一种新的范式来处理图像分割任务。这个范式不依赖于传统的预训练加微调&#xff08;pretrainfinetune&#xff09;方法&#xff0c;而是通过提示&#xff08;prompt&#xff09;加上…

关于我转生从零开始学C++这件事:升级Lv.10

❀❀❀ 文章由不准备秃的大伟原创 ❀❀❀ ♪♪♪ 若有转载&#xff0c;请联系博主哦~ ♪♪♪ ❤❤❤ 致力学好编程的宝藏博主&#xff0c;代码兴国&#xff01;❤❤❤ 盘古开天辟地&#xff0c;大伟五一更新。大家好哇&#xff0c;大伟今天继续给大家来更新我们的C&#xff1a;…

Redis---------实现查询缓存业务

目录 数据库与缓存之间的工作业务逻辑&#xff1a; 接下来看查询缓存代码实现&#xff0c;主要是捋清楚业务逻辑&#xff0c;代码实现是死的&#xff1a; Controller: Service: P37作业实现&#xff1a;总体逻辑跟上面的业务逻辑差不多 Controller&#xff1a; Service&#…

MATLAB 代数

MATLAB 代数 到目前为止&#xff0c;我们已经看到所有示例都可以在MATLAB及其GNU&#xff08;也称为Octave&#xff09;中运行。但是&#xff0c;为了求解基本的代数方程&#xff0c;MATLAB和Octave几乎没有什么不同&#xff0c;因此我们将尝试在单独的部分中介绍MATLAB和Octa…
最新文章