C/C++语言基础--C++运算符重载以及其重载限制

news/2024/9/28 12:16:19 标签: c语言, c++, java, visual studio code, 开发语言, visualstudio

本专栏目的

  • 更新C/C++的基础语法,包括C++的一些新特性

前言

  • 通过前面几节,我们介绍了C++的类与对象、构造与析构函数、拷贝、成员变量、特殊变量等相关知识,这一篇将详细介绍了C++的运算符重载,我感觉这是C++的一个很伟大的发明,让自定义类型有了和普通数据一样进行运算;
  • C语言后面也会继续更新知识点,如内联汇编;
  • 本人现在正在写一个C语言的图书管理系统,1000多行代码,包含之前所学的所有知识点,包括链表和顺序表等数据结构,请大家耐心等待!!预计国庆前写完更新。

文章目录

    • 什么是运算符重载
    • 运算符重载的意义
    • 运算符重载限制
      • 可以重载的运算符
      • 不能重载的运算符
    • 运算符重载规则
    • 运算符重载方法
      • 两种重载方法
      • 注意点
    • 单目运算符重载
      • 单目运算符
      • 重载自增、自减法
    • 双目运算符重载
    • 类型转换重载

什么是运算符重载

运算符重载,就是赋予运算符新的含义。它是重载系统内部运算符的函数,是实现类静态多态性的方式之一。它本质上是函数重载

让我们来看一下这个需求,需要对比A1同学和A2同学年龄的大小:

// 假设都属于学生类
Student A1("wy", 18), A2("Wq", 19);
// 想要对比谁的年龄大,试想一下,能不能像正常比较大小那样直接比较呢?
cout << A1 < A2 << endl;

答案当然是可以的,这个就是我们这节课要学习的**“运算符重载”**,这样进行重载后,类更像是一种自定义数据类型。

实际上,我们已经在不知不觉之中使用了运算符重载。列如:

  • 我们习惯使用的对整数,浮点数运用+、-、*、/,其实计算机对整数和浮点数的操作过程是不一样的,这个主要是整数和浮点数的编码规则不同(详细请看《深入了解计算机系统》),但由于C++已经对运算符进行了重载,所以才能都适用。

  • 又如<<本来是左移运算符,但在输出操作中,与cout搭配,当作输出流运算符了

运算符重载的意义

我们平常常见的算术运算符、逻辑运算符等运算符都是系统库函数里面已经存在的,所以运算符可以直接用于我们常用的数据类型。然而对于我们自定义的类实例化的对象,系统没有与之相关的运算符可以操作,但是为了使我们编写程序时更加便捷,C++提供了一种方式——运算符重载,来满足我们对于类对象进行的操作。

总的来说就是,C++的数据是对类的抽象,运算符重载就可以让我们自定义类型可以像平常数据类型一样进行运算

运算符重载限制

C++中绝大部分的运算符允许重载,少部分不允许重载,详细描述如下(忘了现查即可):

可以重载的运算符

  • 算术运算符:+ - * / %
  • 自增、自减运算符:++ –
  • 位运算符:| & ~ ^ << >>
  • 逻辑运算符:|| && !
  • 关系运算符:== != < > <= >=
  • 赋值运算符:= += -= /= %= &= |= ^= <<= >>=
  • 单目运算符:+ - * &
  • 动态内存分配:new delete new[] delete[]
  • 其他运算符:() -> , []

不能重载的运算符

  • . 成员访问运算符
  • :: 域运算符
  • .* ->* 成员指针访问运算符
  • szieof 长度运算符
  • ?: 条件运算符

运算符重载规则

  • 重载运算符函数可以对运算符作出新的解释﹐但原有基本语义不变:
    • 不改变运算符的优先级
    • 不改变运算符的结合性
    • 不改变运算符所需要的操作数
    • 不能创建新的运算符
  • 语法:

在这里插入图片描述

  • 一个运算符被重载后,原有意义没有失去,只是定义了相对一特定类的一个新运算符。

举例,上面比较年龄的实现:

#include <iostream>

using namespace std;

class Student
{
public:
	Student(std::string name, int age)
		:m_name(name),
		m_age(age)
	{

	}

	bool operator<(const Student& other) 
	{
		return this->m_age < other.m_age;
	}

private:
	std::string m_name;
	int m_age;
};

int main()
{
	Student a1("w", 18), a2("y", 19);

	bool res = a1 < a2;

	cout << boolalpha <<  res << endl;

	// 输出结果: true

	return 0;
}

为什么直接一下操作输出呢?

cout << a1 < a2;

因为优先级的问题,<< 大于 < ,如果使用以上代码,则实际它运行的是:

(cout << a1) << a2;

而类是输出不了的,他不是标准类型,不能匹配,需要我们自定义内容,具体怎么操作,还需要往下学习。

运算符重载方法

两种重载方法

重载为成员函数全局(友元)函数(友员函数非必要不用)

// 实现字符串内容连接
MyObject operator+(const char* str)
{
    MyObject temp(size + strlen(str) + 1);
    strcpy(temp.c_str, c_str);  // 拷贝
    strcat(temp.c_str, str);  // 连接
}

两种形式的选择:

  • 左操作数(或者只有左操作数并且)本类的对象时,可选用成员函数形式。
MyObject& operator=(const MyObject& other);
MyObject& operator=(const char* str);
  • 左操作数不是本类的对象,必须采用非成员函数的形式,一般是友元函数

这一种情况一般用于输出对象,因为对象不是标准类型,他不能直接输出,那如果我想要执行一下操作就直接输出该学生信息呢?

Student a1("wy", 18);
cout << a1;

这个时候就可以用我们的运算符重载了,如下:

#include <iostream>

using namespace std;

class Student
{
	friend ostream& operator<<(ostream& out, const Student& other);
public:
	Student(std::string name, int age)
		:m_name(name),
		m_age(age)
	{

	}

	bool operator<(const Student& other) 
	{
		return this->m_age < other.m_age;
	}
private:
	std::string m_name;
	int m_age;
};

// 友员一般在类外实现,但是在类内中间实现也行
ostream& operator<<(ostream& out, const Student& other)
{
	out << "Name: " << other.m_name << ", Age: " << other.m_age << endl;
	return out;
}

int main()
{
	Student a1("w", 18), a2("y", 19);

	cout << a1;
    
    // 输出:Name: w, Age: 18

	return 0;
}

当然也可以重载输入:

friend istream& operator>>(istream& out, const Student& other);

注意点

一般单目运算符最好被重载为成员函数;双目运算符重载为友元函数

注意:有些运算符不能重载为友元函数,它们是:=,(),[]和->。

  • 具有可交换性的双目运算符最好两种形式都有(成员函数时适用左操作数为本类对象,友元函数时适用左操作数为其他类的对象),也就是需要重载两种运算符1
// 如下
"123" + zc;
zc + "123";  // 两种都需要重载

·

单目运算符重载

什么是单目,什么是双目呢?顾名思义,就是运算符的操作数的个数

  • 单目就是一个操作数,比如++,a++,操作数只有一个a,写成a++b是非法的。
  • 双目就是两个操作数,最熟悉的就是+,a+b,计算ab的和
  • 三目就是三个操作数,目前只有一个条件运算符,?运算符,比如a?b;c,当a的值为真时,结果是b,否则结果是c。

单目运算符

一些只需要一个操作数的运算符称为一元运算符(或单目运算符)。

重载自增、自减法

  1. 返回类型不同

  2. 形参不同

  3. 效率不同

    Student& operator++() 
    {
    	this->m_age += 1;
    	return* this;
    }
    
    Student operator++(int)
    {
    	Student temp = *this;
    	++* this;
    	return temp;
    }
    

双目运算符重载

一些需要两个操作数的运算符称为二元运算符(或双目运算符)

// 对年龄相加
int operator+(const Student& a1, const Student& a2)
{
    return a1.m_age + a2.m_age;
}

同样的道理,三目就是操作数为三个。

类型转换重载

类型重载就是没有返回值类型的,自动推断,如下一个例子:

//类型转换强转
//1.没有返回类型
operate int()
{
    return 
}

//
class Text
{
private:
    int m_a;
public:
    operator int()
    {
        return int(m_a);
    }
}

int main()
{
    Text a(99);
    int b = a;    //将对象赋值给一个变量
    rerurn 0;
}
  • 上面a(99)运算过程,a会在class找,找能赋值的运算符重载

注意: 与运算符 = 重载的区别, a = 99; 这样是 = 重载,将一个值赋值给对象 , 即左操作数不是本类对象


http://www.niftyadmin.cn/n/5681081.html

相关文章

g2o 中定义好的常用顶点类型

前言 一般来说定义 Vertex 需要重写这几个函数 // 读盘、存盘函数&#xff0c;不需要进行读/写操作的话&#xff0c;仅仅声明一下就可以 virtual bool read(std::istream& is); virtual bool write(std::ostream& os) const;// 设置被优化顶点的初始值 virtual void s…

【x**3专享#2】编译 uboot 和 kernel 的文件结构

虚拟机交叉编译环境配置及内核编译步骤说明书 请先查看前篇文章内容 1. 获取虚拟机 IP 地址 打开虚拟机终端&#xff0c;执行以下命令查看虚拟机 IP 地址&#xff1a;ifconfig或者ip addr记录 eth0 或 ens33 等网络接口的 inet 后面的 IP 地址 2. 使用 Xftp 连接虚拟机 打开…

set和map结构的使用

个人主页&#xff1a;敲上瘾-CSDN博客 个人专栏&#xff1a;游戏、数据结构、c语言基础、c学习、算法 目录 一、序列式容器和关联式容器 二、set和multiset 1.insert 2.erase 3.find 4.count 三、map和mapmulti 1.pair 2.insert 3.find 4.operator[ ] 5.erase 6.lo…

后端学习路线

后端学习路线 一、编程语言 至少需要学习一门编程语言&#xff0c;建议学习JAVA和GO语言。 二、数据库 数据库分为关系型数据库和非关系型数据库&#xff0c;区别在于分关系型数据库常用于大数据&#xff0c;而非关系型数据库一般不在大数据方面使用。 关系型数据库&#x…

基于Java开发的(控制台)模拟的多用户多级目录的文件系统

多级文件系统 1 设计目的 为了加深对文件系统内部功能和实现过程的理解&#xff0c;设计一个模拟的多用户多级目录的文件系统&#xff0c;并实现具体的文件物理结构、目录结构以及较为完善的文件操作命令集。 2 设计内容 2.1系统操作 操作命令风格&#xff1a;本文件系统的…

图论(dfs系列) 9/27

一、二维网格图中探测环 题意: 给定一个二维数组grid,如果二维数组中存在一个环&#xff0c;处于环上的值都是相同的。返回true&#xff1b;如果不存在就返回false&#xff1b; 思路&#xff1a; 在以往的dfs搜索中&#xff0c;都是往四个方向去dfs&#xff1b;但是在这一道…

《凡人歌》中的IT职业启示录

《凡人歌》是由中央电视台、正午阳光、爱奇艺出品&#xff0c;简川訸执导&#xff0c;纪静蓉编剧&#xff0c;侯鸿亮任制片&#xff0c;殷桃、王骁领衔主演&#xff0c;章若楠、秦俊杰、张哲华、陈昊宇主演的都市话题剧 &#xff0c;改编自纪静蓉的小说《我不是废柴》。该剧于2…

SpringBoot的概述与搭建

目录 一.SpringBoot的概述 二.SpringBoot 特点 三.SpringBoot 的核心功能 3.1起步依赖 3.2自动配置 四.SpringBoot 开发环境构建 五.SpringBoot 配置文件 六.SpringBoot数据访问管理 七.springboot注解 八.springboot集成mybatis 九.springboot全局异常捕获与处理 一…