C++基础教程面向对象(学习笔记(18))

运算符重载简介

您在前面学习了函数重载,它提供了一种具有相同名称的多个函数的函数调用的创建和解析机制,只要每个函数都有一个唯一的函数原型。这允许您创建函数体以使用不同的数据类型,而无需为每个函数体考虑唯一的名称。

在C ++中,运算符是作为函数实现的。通过在运算符函数上使用函数重载,您可以定义使用不同的数据类型的运算符版本(包括您编写的类)。使用函数重载到重载运算符称为运算符重载。

在本章中,我们将研究与运算符重载相关的主题。

运算符作为函数

请考虑以下示例:

int x = 2;
int y = 3;
std::cout << x + y << endl;

编译器带有一个用于整数操作数的加号运算符(+)的内置版本 - 该函数将整数x和y加在一起并返回整数结果。当您看到表达式时x + y,可以将其转换为函数调用operator+(x, y)(其中operator +是函数的名称)。

现在考虑这个类似的片段:

double z = 2.0;
double w = 3.0;
std::cout << w + z << endl;

编译器还带有一个内置版本的加法运算符(+),用于双操作数。表达式w + z成为函数调用operator+(w, z),函数重载用于确定编译器应该调用此函数的double版本而不是int版本。

现在考虑如果我们尝试添加用户定义类的两个对象会发生什么:

Mystring string1 = "Hello, ";
Mystring string2 = "World!";
std::cout << string1 + string2 << endl;

在这种情况下你会发生什么?直观的预期结果是字符串“Hello,World!”将被打印在屏幕上。但是,因为Mystring是用户定义的类,所以编译器没有可用于Mystring操作数的加法运算符的内置版本。所以在这种情况下,它会给我们抛出一个错误。为了使它像我们想要的那样工作,我们需要编写一个重载函数来告诉编译器+运算符应该如何使用两个类型为Mystring的操作数。我们将在下一课中介绍如何执行此操作。

解决重载运算符

在评价包含运算符的表达式时,编译器使用以下规则:

如果所有操作数都是基本数据类型,则编译器将调用内置例程(如果存在)。如果不存在,编译器将产生编译器错误。
如果任何操作数是用户数据类型(例如,您的某个类或枚举类型),编译器将查看该类型是否具有可以调用的匹配重载操作符函数。如果找不到,它将尝试将一个或多个用户定义的类型操作数转换为基本数据类型,以便它可以使用匹配的内置运算符(通过重载的类型转换,我们将在后面介绍这一章)。如果失败,则会产生编译错误。

运算符重载有哪些限制?

首先,几乎所有C ++中的现有运算符都可以重载。例外情况是:条件(??,sizeof,范围(:?,成员选择器(.)和成员指针选择器(.*)。

其次,您只能重载存在的运算符。您无法创建新运算符或重命名现有运算符。例如,您无法创建运算符**来执行指数。

第三,重载运算符中的至少一个操作数必须是用户定义的类型。这意味着你不能重载加号运算符来使用一个整数和一个double。但是,您可以重载加号运算符以使用整数和Mystring。

第四,不可能改变运营商支持的操作数的数量。

最后,所有运算符都保持其默认优先级和关联性(无论它们用于什么),这都无法更改。

一些新程序员试图使按位XOR运算符(^)重载以进行求幂。但是,在C ++中,operator ^的优先级低于基本算术运算符,这会导致表达式的计算结果不正确。

在基础数学中,取幂在基本算术之前解析,因此4 + 3 ^ 2解析为4 +(3 ^ 2)=> 4 + 9 => 13.
但是,在C ++中,算术运算符的优先级高于运算符^,所以4 + 3 ^ 2解析为(4 + 3)^ 2 => 7 ^ 2 => 49。

每次使用它时,您都需要明确地将指数部分括起来(例如4 +(3 ^ 2)),以使其正常工作,这不直观,并且可能容易出错。

由于这个优先级问题,通常只能以与原始意图类似的方式使用运算符。

规则:当重载运算符时,最好保持运算符的功能尽可能接近运算符的原始意图。

此外,由于运营商没有描述性名称,因此并不总是清楚他们打算做什么。例如,operator +可能是字符串类进行字符串连接的合理选择。但是运营商呢?你期望做什么?目前还不清楚。

规则:如果应用于自定义类的运算符的含义不清晰直观,请改用命名函数。

在这些范围内,您仍然会发现许多有用的功能可以为您的自定义类重载!您可以重载+运算符以连接用户定义的字符串类,或者将两个Fraction类对象一起添加。您可以重载<<运算符,以便将类打印到屏幕(或文件)。您可以重载相等运算符(==)以比较两个类对象。这使得运算符重载C ++中最有用的功能之一 - 只是因为它允许您以更直观的方式使用类。

在即将到来的课程中,我们将深入研究超载不同类型的运营商。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值