C++基础知识(五:运算符重载)

简介: 运算符重载是C++中的一项强大特性,它允许程序员为自定义类型(如类或结构体)重新定义标准运算符的行为,使得这些运算符能够适用于自定义类型的操作。这样做可以增强代码的可读性和表达力,使得代码更接近自然语言,同时保持了面向对象编程的封装性。


运算符重载是C++中的一项强大特性,它允许程序员为自定义类型(如类或结构体)重新定义标准运算符的行为,使得这些运算符能够适用于自定义类型的操作。这样做可以增强代码的可读性和表达力,使得代码更接近自然语言,同时保持了面向对象编程的封装性。

基本原则

  1. 保留原有语义:重载的运算符应当保持其原有的基本意义,比如加号+通常用于表示相加或组合的概念。
  2. 不要滥用:虽然运算符重载很灵活,但过度或不恰当的使用会使得代码难以理解和维护。
  3. 一致性:运算符的行为应与内置类型或大家公认的约定保持一致,以减少学习和使用的障碍。
  4. 明确性:确保重载的运算符在其上下文中具有明确的意义,避免引起混淆。

重载类型

  • 二元运算符:如+-*/等,需要至少两个操作数。
  • 一元运算符:如++--!等,只涉及一个操作数。
  • 赋值运算符:如=, +=, -=, *=, /=等,有特殊的规则,比如需要考虑自赋值的情况。
  • 转换运算符:如operator T(),允许类的对象隐式或显式转换为另一种类型。
  • I/O流运算符:如<<>>,用于与标准输入输出流集成,增强类的可读性和可写性。
  • 条件运算符:如<>==等,用于比较操作。
  • 下标运算符[]:使得对象可以像数组那样通过索引访问。
  • 函数调用运算符():允许对象像函数一样被调用。

【1】运算符重载函数名格式

返回值  operator运算符(参数)

{

  //函数体

}

【2】运算符重载的目的

让自己定义的类也能直接参与运算

运算符重载的要求:

  1. 不能创造运算符,必须对已有的运算符重载
  2. 不能更改运算符本身的功能,+运算重载后实现乘法运算

【3】运算符重载函数的格式

  1. 成员函数的格式:给哪个类重载运算符,就把重载函数定义为哪个类的成员函数
  2. 全局函数的格式:需要在类内声明全局函数为友元函数

成员函数版的运算符重载一定比全局函数版的运算符重载一个参数,成员函数本身提供了一个类对象

【4】算数运算符的重载

算术运算都是双目运算:

格式:L # R  ---->需要两个类对象作为参数

结果:右值

参数:运算过程中不需要修改操作数,可以定义为const

示例:

#include <iostream>
class Complex {
public:
    // 默认构造函数
    Complex() : real(0), imag(0) {}
    // 带参数的构造函数
    Complex(double r, double i) : real(r), imag(i) {}
    // 重载 "+" 运算符
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
    // 显示复数的方法
    void display() const {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
private:
    double real;   // 实部
    double imag;   // 虚部
};
int main() {
    Complex num1(3, 4);  // 创建复数 3 + 4i
    Complex num2(1, 2);  // 创建复数 1 + 2i
    Complex sum = num1 + num2;  // 使用重载的 "+" 运算符
    std::cout << "Sum of the two complex numbers: ";
    sum.display();  // 输出相加后的复数
    return 0;
}

image.gif

image.gif 编辑

【5】赋值运算符的重载

operator= :拷贝赋值函数

+=、-=···运算符的重载

格式:L # R

结果:对左操作数的修改,是一个左值

参数:左操作数运算过程中可以修改,右操作数不能修改

示例:

// 赋值运算符重载
Complex& operator=(const Complex& other) {
    if (this != &other) {  // 防止自我赋值
        real = other.real;
        imag = other.imag;
    }
    return *this;
}

image.gif

【6】条件运算符的重载

<   >·····

格式:L # R

结果:bool类型的真值或者假值

参数:运算过程中不需要修改操作数,可以定义为const

bool operator>(Complex &c1,Complex &c2)

{}

示例:

// 小于运算符重载
bool operator<(const Complex& other) const {
    return (real < other.real) || ((real == other.real) && (imag < other.imag));
}

image.gif

【7】()运算符的重载

  1. 对()运算符,调用函数的性质重载
  2. 对()强转的性质重载    float a;  int(a);

格式:operator 数据类型(){}    ---->因为强转类型已经明确了返回值类型

示例:

// 下标运算符重载
double& operator[](int index) {
    if (index == 0) return real;
    else if (index == 1) return imag;
    else throw std::out_of_range("Index out of range for Complex number.");
}

image.gif

【8】自增自减运算符的重载

a++、 ++a、

前自增:

成员函数:Complex &operator++(){}

全局函数:Complex &operator++(Complex &c1){}

后自增: ----->需要使用哑元和前自增区分

成员函数:Complex &operator++(int){}

全局函数:Complex &operator++(Complex &c1,int){}

示例:

// 自增运算符前置版本
Complex& operator++() {
    ++real;
    ++imag;
    return *this;
}
// 自增运算符后置版本
Complex operator++(int) {
    Complex temp(*this);
    ++(*this);
    return temp;
}
// 自减运算符前置版本
Complex& operator--() {
    --real;
    --imag;
    return *this;
}
// 自减运算符后置版本
Complex operator--(int) {
    Complex temp(*this);
    --(*this);
    return temp;
}

image.gif

【9】不能重载的运算符

  1. sizeof()
  2. 成员访问运算符.    
  3. 指针访问运算符  *  ---->对指针访问
  4. ::  域限定符
  5. a?a:b    
相关文章
|
25天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
59 5
|
3月前
|
C++
C++(十五) 运算符重载
C++中的运算符重载允许对已有运算符的功能进行重新定义,从而扩展语言功能、简化代码并提升效率。重载遵循特定语法,如 `friend 类名 operator 运算符(参数)`。重载时需注意不可新增或改变运算符数量、语义、优先级、结合性和返回类型。常见示例包括双目运算符 `+=` 和单目运算符 `-` 及 `++`。输入输出流运算符 `&lt;&lt;` 和 `&gt;&gt;` 也可重载。部分运算符只能作为成员函数重载。
|
5月前
|
C语言 C++ 开发者
C++基础知识(一:命名空间的各种使用方法)
C++在C的基础上引入了更多的元素,例如类,类的私密性要比C中的结构体更加优秀,引用,重载,命名空间,以及STL库,模板编程和更多的函数,在面向对象的编程上更加高效。C语言的优势则是更加底层,编译速度会更快,在编写内核时大多数都是C语言去写。 在C++中,命名空间(Namespace)是一种组织代码的方式,主要用于解决全局变量、函数或类的命名冲突问题。命名空间提供了一种封装机制,允许开发者将相关的类、函数、变量等放在一个逻辑上封闭的区域中,这样相同的名字在不同的命名空间中可以共存,而不会相互干扰。
119 0
|
6月前
|
存储 编译器 C++
【C++】:拷贝构造函数和赋值运算符重载
【C++】:拷贝构造函数和赋值运算符重载
31 1
|
6月前
|
C++ 索引
C++核心技术要点《运算符重载》
C++核心技术要点《运算符重载》
54 2
|
5月前
|
C++
C++基础知识(二:引用和new delete)
引用是C++中的一种复合类型,它是某个已存在变量的别名,也就是说引用不是独立的实体,它只是为已存在的变量取了一个新名字。一旦引用被初始化为某个变量,就不能改变引用到另一个变量。引用的主要用途包括函数参数传递、操作符重载等,它可以避免复制大对象的开销,并且使得代码更加直观易读。
|
5月前
|
算法 编译器 C++
C++基础知识(三:哑元和内联函数和函数重载)
在C++编程中,"哑元"这个术语虽然不常用,但可以理解为在函数定义或调用中使用的没有实际功能、仅作为占位符的参数。这种做法多见于模板编程或者为了匹配函数签名等场景。例如,在实现某些通用算法时,可能需要一个特定数量的参数来满足编译器要求,即使在特定情况下某些参数并不参与计算,这些参数就可以被视为哑元。
|
5月前
|
C++
C++基础知识(四:类的学习)
类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。
|
5月前
|
存储 编译器 C++
C++基础知识(六:继承)
多态是面向对象编程的四大基本原则之一,它让程序能够以统一的接口处理不同的对象类型,从而实现了接口与实现分离,提高了代码的灵活性和复用性。多态主要体现在两个层面:静态多态(编译时多态,如函数重载)和动态多态(运行时多态,主要通过虚函数实现)。
|
5月前
|
存储 编译器 C++
C++基础知识(七:多态)
多态是面向对象编程的四大基本原则之一,它让程序能够以统一的接口处理不同的对象类型,从而实现了接口与实现分离,提高了代码的灵活性和复用性。多态主要体现在两个层面:静态多态(编译时多态,如函数重载)和动态多态(运行时多态,主要通过虚函数实现)。

热门文章

最新文章