首页 > 编程语言 >C++学习笔记-operator关键字:重载与自定义操作符

C++学习笔记-operator关键字:重载与自定义操作符

时间:2024-07-25 19:25:06浏览次数:15  
标签:函数 自定义 C++ 重载 Complex 操作符 operator

在C++编程中,operator关键字扮演着极其重要且独特的角色。它允许开发者为内置类型或自定义类型重载或定义新的操作符行为。这一特性极大地增强了C++的表达能力,使得代码更加直观、易于理解和维护。本文将深入探讨C++中operator关键字的使用,包括操作符重载和自定义操作符的基本概念、语法、使用场景以及注意事项。

一、操作符重载定义(Operator Overloading)

1.1 基本概念

操作符重载是C++语言的一个特性,它允许你重新定义或“重载”已存在的操作符(如+、-、*、/等)在特定类型上的行为。这意呀着,你可以为自定义类型(如类)定义这些操作符如何工作,使得它们能够像内置类型那样进行算术运算或逻辑操作。

1.2 误区

需要注意的是,C++并不支持真正意义上的“自定义操作符”,即你不能创造全新的、从未在C++中定义过的操作符符号。然而,你可以通过重载现有的操作符来赋予它们新的意义,这在一定程度上实现了类似自定义操作符的效果。

二、操作符重载实现

2.1 重载规则

在C++中,不是所有的操作符都可以被重载。以下是一些可以重载的操作符列表(注意,这里只列出了部分常用操作符,完整列表请参考C++标准):

  • 算术操作符:+、-、*、/、%、++、–
  • 关系操作符:==、!=、<、<=、>、>=
  • 逻辑操作符:!、&&、||(但通常不建议重载这些操作符,因为它们的行为与短路评估紧密相关)
  • 位操作符:&、|、^、~、<<、>>
  • 赋值操作符:=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
  • 其他操作符:()(函数调用)、[](下标)、->*(指向成员的指针运算符)、new和delete(虽然这些操作符通常不被重载,但了解它们的存在是有益的)

此外,还有一些操作符是不能被重载的,如.(成员访问操作符)、::(作用域解析操作符)、sizeof(获取对象或类型大小)、typeid(获取类型的类型信息)等。

2.2 重载方式

操作符重载可以通过成员函数或友元函数来实现。选择哪种方式取决于操作符需要访问的类成员以及操作符的预期行为。

  • 成员函数重载:当操作符需要一个操作数(通常是左侧操作数)作为类的一个对象时,通常使用成员函数重载。例如,重载+操作符以实现两个自定义类型对象的加法时,如果加号左侧的对象是自定义类型的实例,则可以将+操作符重载为成员函数。
  • 友元函数重载:当操作符需要访问类的私有或保护成员,或者当两个操作数都是自定义类型时,通常使用友元函数重载。友元函数不是类的成员函数,但它可以访问类的私有和保护成员。因此,它提供了一种灵活的方式来重载需要访问类内部状态的操作符。

2.3注意事项

  • 不要重载所有操作符:只重载那些对类有意义的操作符,避免造成混淆。
  • 保持操作符的语义:尽量保持操作符的直观性和原有语义,避免误导使用者。
  • 避免重载&&、||和,:这些操作符的短路行为在重载时可能难以正确实现,且容易引发错误。
  • 成员函数与友元函数的选择:根据操作数的类型和操作符的语义来选择合适的重载方式。

2.4 语法示例

以下是一个简单的示例,展示了如何为自定义的Complex类重载+操作符:

#include <iostream>  
  
class Complex {  
public:  
    double real, imag;  
  
    // 构造函数  
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}  
  
    // 成员函数重载+操作符  
    // 注意:这里我们返回了一个Complex对象的副本  
    Complex operator+(const Complex& rhs) const {  
        return Complex(real + rhs.real, imag + rhs.imag);  
    }  
  
    // 声明友元函数来重载<<操作符  
    friend std::ostream& operator<<(std::ostream& os, const Complex& c);  
};  
  
// 定义友元函数来重载<<操作符  
// 注意:这个函数不是Complex类的成员函数  
std::ostream& operator<<(std::ostream& os, const Complex& c) {  
    os << c.real << (c.imag >= 0 ? "+" : "") << c.imag << "i";  
    // 如果imag为负,则不打印加号  
    return os; // 返回ostream对象以支持链式调用  
}  
  
int main() {  
    Complex c1(1, 2);  
    Complex c2(3, 4);  
  
    // 使用重载的+操作符  
    Complex c3 = c1 + c2;  
  
    // 使用重载的<<操作符输出复数  
    std::cout << "c1 + c2 = " << c3 << std::endl;  
  
    return 0;  
}

代码中在自定义一个Complex(复数)类,成员变量有real(实部)和imag(虚部)。然后,我们为这个类重载了+操作符,使其能够接受另一个Complex对象作为参数,并返回一个新的Complex对象,该对象包含了两个复数相加的结果。

接下来,我们声明了operator<<作为Complex类的友元函数,并在类定义外部对其进行了定义。这个函数接受一个std::ostream引用和一个const Complex&引用作为参数,将复数以“实部+虚部i”的格式输出到流中(如果虚部为正,则输出加号;如果虚部为负,则不输出加号),并返回std::ostream对象的引用以支持链式调用。

在main函数中,我们创建了两个Complex对象c1和c2,使用重载的+操作符将它们相加,得到结果c3,然后使用重载的<<操作符将c3输出到控制台。输出结果如下:
在这里插入图片描述

标签:函数,自定义,C++,重载,Complex,操作符,operator
From: https://blog.csdn.net/chen_mp/article/details/140646164

相关文章

  • 设计模式C++001__模板方法
    设计模式C++001__模板方法“组件协作”模式:现代软件专业分工之后的第一个结果就是“框架与应用程序的划分”,组件“协作”模式通过晚绑定,来实现框架与应用程序之间的松耦合。包括:模版方法,观察者模式,策略模式1、模板方法模式:动机:在软件构建过程中,对于一项任务,它常常有稳定的整......
  • 设计模式C++002__策略模式
    设计模式C++002__策略模式1、动机:在软件构建过程中,某些对象使用的算法是多种多样的,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。?如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?......
  • 设计模式C++003__观察者模式
    设计模式C++003__观察者模式1、动机:在软件构建过程中,我们需要为某些对象建立一种“通过依赖关系”--一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使得软件不好抵御变化。?使用面向对象技术,可以将这种依赖关系弱化,并形成......
  • 设计模式C++004__装饰器模式
    设计模式C++004__装饰器模式在软件组件设计中,如果职责划分不清晰,使用继承得到的结果往往会随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候关键是划清责任。单一职责模式分类中的设计模式:装饰器模式,桥模式1、装饰器模式:动机:在某些情况下,我们可能会“过渡地使用继承来扩......
  • 设计模式C++005__桥模式
    设计模式C++005__桥模式也是组合模式的具体体现。1、动机:由于某些类型的古有的实现逻辑,使得他们具有两个变化的维度,乃至多个维度的变化。?如何应对这种“多维度的变化”,如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度。2、桥模式:将......
  • 设计模式C++007__抽象工厂方法模式
    设计模式C++007__抽象工厂方法模式抽象工厂方法1、动机:在软件系统重,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。?如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种封装机制,来避免客户程序和这种“多系列具体对象......
  • c++学习笔记(五)
    目录文件操作文本文件写文件include读文件include二进制文件写文件读文件文件操作程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放通过文件可以将数据持久化c++中对文件操作需要包含头文件文件类型分为两种:文本文件-文件以文本的ASCII码形式存储在计算......
  • C++| STL之unordered_map(哈希表)和map
    前言:Leetcode题目中有一个哈希表的专题,自己实现的话没必要,可以直接用STL现成的unordered_map函数,提到unordered_map就不得不提到map,于是有了此篇相关知识点的汇总。unordered_map和mapkey和valueunordered_map使用map原理对比unordered_map使用对比unordered_mapke......
  • 现代 C++ 中的初始化
    原文链接:https://www.cnblogs.com/tengzijian/p/17964231本文尝试回答:现代C++有哪几种初始化形式?分别能够用于什么场景?有什么限制?MyClassobj(); 为什么没有调用默认无参构造函数创建一个对象?newint 和 newint() 有什么区别?直接初始化、拷贝初始化、列表初始化、默......
  • SSM-网络课程系统-29230(免费领源码+开发文档)可做计算机毕业设计JAVA、PHP、爬虫、APP
    SSM网络课程系统摘 要本论文主要论述了如何使用SSM框架开发一个网络课程系统,将严格按照软件开发流程进行各个阶段的工作,采用B/S架构Java技术,面向对象编程思想进行项目开发。在引言中,将论述网络课程系统的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统......