前言:《c++类和数据结构》这本书是寒假前在学校图书馆借的,然后寒假基本没怎么看,前两天回学校翻了翻发现挺厉害的…于是有了一个大胆的想法:跟着书做笔记…虽然大部分都是跟着书敲…虽然不知道能坚持几天…不管了敲了再说…
PS:本文纯粹本人无聊跟着书乱敲,毫无逻辑,没啥营养!!慎读!!
重载运算符、类模板和抽象
1.重载运算符
运算符的概念:运算符通常指的是一些符号,作用于一个或者多个变量或常量,产生一个结果。如:+、<=和&&等。有时候结果是经计算的得出的值,有时候结果是false或者true,运算符总能获得某些类型的结果,否则就没有理由使用运算符了。
但我们现在需要改变一下思考方式,把运算符看作是一次函数调用,而不是简单的符号,调用函数的返回值取代了函数本身,也就是运算符的运算结果,事实上,所有我们所用的运算符都是调用程序员所编写的函数才能实现功能的。
例如。如果函数xdd返回一个整型数3,那么表达式
x = xdd() + 2;
将把值5存放到x中。在这是因为xdd()被其返回值3取代,然后3加上2得到5,最后将5存储在x中。同理,在表达式
if (x > y)
中, >是重载运算符,表达式 x > y 是函数调用。因此整个表达式 x > y 将被函数的返回值取代。在这种情况下,该函数的返回值可能是一个布尔类型,因此整个表达式 x > y 将被函数执行完后所返回的true或者false取代。
在以上的例子中,如果 x , y都是对象(如整型),且重载运算符被定义了,那么c++就知道如何去做了;因此,重载运算符只能为对象编写,而且必须为作用于对象的运算符编写重载运算符函数。
例如,我们定义一个结构
struct CarType {
string maker;
int year;
float price;
};
假定我们将myCar声明为该结构的一个对象,并且为该对象的所有数据成员赋值。然后我们编写下述代码:
if (myCar > 2000)
cout << "My car is more than 2000!" << endl;
这时,c++不知道如何处理这段代码,因为c++不知道应该拿myCar中的哪一个变量和2000比较,所以我们必须通过编写一个c++能够执行的函数,告诉c++应该如何处理这一情况。
因为运算符的广泛性,所以有许多种方式进行编写。我们将讨论限定于二元运算符(binary operator)——而且只是用于计算或者比较的运算符,一个二元运算符只作用于2个操作数。
在c++中,二元运算符通常左边有一个操作数,右边有一个操作数。前面讲过,为了编写重载运算符函数,两个操作数必须有一个是对象。如果左边的操作数是结构的对象,那么整个函数定义通常位于结构定义内部,然后运算符右边的操作数作为参数传递给函数。下面是一个描述这样一个函数的简单程序:
//A program that uses an overloaded operator in a struct
#include<iostream>
#include<string>
using namespace std;
struct CarType {
string maker;
int year;
float price;
bool operator > (int num) {
if (price > num) return true;
return false;}
};
int main()
{
CarType myCar;
myCar.maker = "Mercedes";
myCar.year = 2019;
myCar.price = 199999.99;
if (myCar > 200000)
cout << "myCar is more than 200000!" << endl;
return 0;
}
注意第10行,这一行代码是重载运算符>的函数定义,该函数是一个返回类型为布尔类型的函数,也正是我们希望的。这里函数名称必须使用关键字operator,后面跟着被重载运算符的符号。
现在,如果把2000也改成CarType的对象 yourCar,会发生什么呢?
if (myCar > yourCar)
cout << "My car is more than 2000!" << endl;
编译器会报错,因为yourCar不是一个整型变量,不能传递给参数