目录
1.【例4.3】将加法运算符重载为适用于复数加法,重载函数作为类的友元函数
2.【例4.4】定义一个字符串类String,用来处理不定长的字符串,重载相等、大于、小于关系运算符,用于两个字符串的等于、大于、小于的比较运算
3.扩展到对三个运算符重载:在String类体中声明三个重载函数是友元函数,并编写相应的函数
2.【例4.5】有一个Time类,数据成员有时、分、秒。要求模拟秒表,每次走一秒,满60秒进位,秒又从零开始计数。满60分进位,分又从零开始计数。输出时、分、秒的值
3.【例4.6】在【例4.5】的基础上增加后++运算符重载函数
(1)【例4-7】在【例4-2】的基础上用<<重载函数输出复数
(1)【例4.8】在【例4.7】的基础上增加流提取运算符>>重载函数,用cin>>输入复数,用cout输出复数
一、什么是运算符重载
1.定义
C++为程序员提供了灵活的手段,让程序员自己定义类,自己设计相应的运算符(必须在已有的运算符基础上设计),使之应用于自己定义的类。与函数重载相似,对已有的运算符赋予新的含义,用一个运算符表示不同功能的运算,这就是运算符重载。
实际上,我们在此之前已经使用了运算符重载。如<<是C++的移位运算符,它又与流对象cout配合作为流插入运算符,这是C++对<<进行了重载处理。
2.实质
运算符重载是对已有的运算符赋予多重含义。
- 必要性:C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)
- 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参
- 编译系统对重载运算符的选择,遵循函数重载的选择原则
3.【例4.1】通过成员函数实现复数的加法
#include <iostream>
using namespace std;
class Complex
{
private:
double real;
double imag;
public:
Complex()
{
real = 0;
imag = 0;
}
Complex(double r, double i)
{
real = r;
imag = i;
}
Complex complex_add(Complex &c2);
void display();
};
Complex Complex::complex_add(Complex &c2)
{
Complex c;
c.real = real + c2.real;
c.imag = imag + c2.imag;
return c;
}
void Complex::display()
{
cout << "(" << real << "," << imag << "i)" << endl;
}
int main()
{
Complex c1(3, 4), c2(5, -10), c3;
c3 = c1.complex_add(c2);
cout << "c1=";
c1.display();
cout << "c2=";
c2.display();
cout << "c1+c2";
c3.display();
return 0;
}
- 在Complex类中定义了complex_add函数做加法,函数的参数是引用对象,作为一个加数。在函数里定义了临时变量c,两个赋值语句相当于:
- c.real=this->real+c2.real;
- c.imag=this->imag+c2.imag;
- 在mian函数中通过对象c1调用加法函数,上面的语句相当于:
- c.real=c1.real+c2.real;
- c.imag=c1.imag+c2.imag;
二、运算符重载的方法
1.格式
运算符重载的方法是定义一个重载运算符函数,在需要时系统自动调用该函数,完成相应的运算。运算符重载实质上是函数的重载。运算符重载函数的格式是:
数据类型 operator 运算符(形参表)
{重载处理}
数据类型:是重载函数值的数据类型
operator是保留字
2.规则和限制
(1)规则和限制
- C++中可以重载除下列运算符外的所有运算符:. .* :: ? :
- 只能重载C++语言中已有的运算符,不可臆造新的
- 不可改变原运算符的优先级和结合性
- 不能改变操作数个数
- 经重载的运算符,其操作数中至少应该有一个是自定义类型
(2)两种形式
- 重载为类成员函数
- 重载为友元函数
(3)运算符函数
- 声明类型
函数类型 operator 运算符(形参)
{
...
}
- 重载为类成员函数时:参数个数=原操作数个数-1(后置++,--除外)
- 重载为友元函数时:参数个数=原操作数个数,且至少应该有一个自定义类型的形参
- 不能重载的运算符有五个:.(成员运算符)、.*(成员指针运算符)、::(域运算符)、sizeof(长度运算符)、?:(条件运算符)
- 重载函数名是由operator和运算符联合组成
- 复数加法运算符重载函数原型可以是:
Complex operator+(Complex &c2);
3.【例4.2】重载运算符,用于两个复数相加
(1)分析
定义一个复数类,用成员函数实现加号的重载函数。两个复数相加结果仍是复数,所以函数的返回值的类型也是复数。用成员函数实现运算符重载函数时,掉用格式是“对象名.成员名”,此时对象就是一个参与运算的操作数,假发还需要另一个操作数,这个操作数用函数的参数传递,参数的类型就是复数类,而运算结果用函数值返回。
(2)代码&结果
#include <iostream>
using namespace std;
class Complex
{
public:
Complex()
{
real = 0;
imag = 0;
}
Complex(double r, double i)
{
real = r;
imag = i;
}
Complex operator +(Complex &c2);
void display();
private:
double real;
double imag;
};
Complex Complex::operator +(Complex &c2)
{
Complex c;
c.real = real + c2.real;
c.imag = imag + c2.imag;
return c;
}
void Complex::display()
{
cout << "(" << real << "," << imag << "i)" << endl;
}
int main()
{
Complex c1(3, 4), c2(5, -10), c3;
c3 = c1 + c2; //直接用+即可
cout << "c1=";
c1.display();
cout << "c2=";
c2.display();
cout << "c1+c2=";
c3.display();
return 0;
}
(3)说明
- 用运算符重载函数取代【例4.1】中的加法成员函数,从外观上看函数体和函数返回值都是相通的
- 在主函数中表达式c3=c1+c2取代了【例4.1】中的c3=c1.complex_add(c2),编译系统将表达式c3=c1+c2解释为c1.operator +(c2),对象c1调用的重载函数operator +,以c2为实参计算两个复数之和
- 在【例4.2】中能否用一个常量和一个复数相加?如c3=3+c2;(错误)。应该定义对象Complex c1(3.0,0);c3=c1+c2;
- 运算符重载后,其原来的功能仍然保留,编译系统根据运算表达式的上下文决定是否调用运算符重载函数。运算符重载和类结合起来,可以在C++中定义使用方便的新数据类型
三、重载运算符的规则
- C++只允许已有的部分运算符实施重载
- 不能重载的运算符有五个
- 重载不改变操作数的个数
- 重载不改变运算符的优先级
- 运算符重载函数不能带默认值参数
- 运算符重载函数必须与自定义类型的对象联合使用,其参数至少有一个类对象或类对象引用
- C++默认提供=和&运算符重载
- 运算符重载函数可以是类成员函数,也可以是类的友元函数,还可以是普通函数
- C++规定赋值运算符、下标运算符、函数调用运算符必须定义为类的成员函数;而输出流插入、输入流提取、类型转换运算符不能定义为类的成员函数