重载运算符的规则
不允许用户定义新的运算符,只能对c++已有的运算符进行重载
C++允许重载的运算符见表10.1(P313),不能重载的运算符有5个,见下页的表
重载不能改变运算符运算对象(操作数)的个数
重载不能改变运算符的优先级、结合性
重载运算符的函数不能有默认的参数
……(见书P313-314)
C++中不允许重载的运算符
运算符重载函数作为类成员函数
重载运算符的函数一般形式:
函数类型 operator 运算符名称(形参表)
{
函数体(对运算符的重载处理)
}
#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& c33)
{
Complex c;
c.real = real + c33.real;
c.imag = imag + c33.imag;
return c;
}
void display()
{
cout << "(" << real << "," << imag << "i)" << endl;
}
private:
double real;
double imag;
};
int main()
{
Complex c1(0,0), c2(5, -10), c3;
c3 = c1.operator+(c2);//c3=c1+c2
cout << "c1 = "; c1.display();
cout << "c2 = "; c2.display();
cout << "c3 = "; c3.display();
}
void AddA(Complex &c1, Complex &c2 )//一般函数
{
real=c1.real+c2.real;
imag=c1.imag+c2.imag;
}
函数调用:
a3.AddA(a1,a2);(相当于:a3=a1.operator+(a2); )
#include<iostream>
using namespace std;
class Room
{
private:double
Length, Wide;
public:
Room(double a = 0.0, double b = 0.0){Length = a;Wide = b;}
void Show(void)
{
cout << "Length=" << Length << '\t' << "Wide=" << Wide << endl;
}
Room operator+(Room&);//重载运算符+,函数原型
};
Room Room::operator + (Room& r) //重载运算符,函数定义
{
Room rr;
rr.Length = Length + r.Length;
rr.Wide = Wide + r.Wide;
return rr;
}
void main(void) {
Room r1(3, 2), r2(1, 4), r3;
r1.Show(); r2.Show();
r3 = r1 + r2; r3.Show();
}
#include<iostream>
using namespace std;
class Complex
{
private:double real, imag;
public:
Complex() { real = 0; imag = 0; }
Complex(double r, double i) { real = r; imag = i; }
void operator ==(const Complex& x) const
{
if ((real == x.real) && (imag == x.imag))
cout << "(" << real << "+" << imag << "i)" << "相等" << "(" << x.real << "+" << x.imag << "i)" << endl;
else
cout << "(" << real << "+" << imag << "i)" << "不相等" << "(" << x.real << "+" << x.imag << "i)" << endl;
}
};
int main(void) {
cout << "请输入第1个复数:";
int a1, b1;
cin >> a1 >> b1;
cout << "请输入第2个复数:";
int a2, b2;
cin >> a2 >> b2;
Complex c1(a1, b1), c2(a2, b2);
c1 == c2;
return 0;
}
运算符重载函数作为友元函数
<类型> <运算符>(形参1,形参2)
{ 函数体 }
说明:形参1与形参2通常为两个参加运算的对象引用。
例如:A a ,b , c;
c=a+b; 实际上是 c=operator+(a, b);
c=++a; 实际上是 c=operator++(a);
c+=a; 实际上是 operator+=( c, a );
说明:参加运算的操作数均作为函数的参数(红色字体表示)
#include<iostream>
using namespace std;
class Complex
{
private: double real, imag;
public:
Complex() { real = 0; imag = 0; }
Complex(double r, double i) { real = r; imag = i; }
friend void operator==(Complex& x1, Complex& x2)
{
if ((x1.real == x2.real) && (x1.imag == x2.imag))
cout << "(" << x1.real << "+" << x1.imag << "i)" << "相等" << "(" << x2.real << "+" << x2.imag << "i)" << endl;
else
cout << "(" << x1.real << "+" << x1.imag << "i)" << "不相等" << "(" << x2.real << "+" << x2.imag << "i)" << endl;
}
};
int main(void) {
cout << "请输入第1个复数:";
int a1, b1;
cin >> a1 >> b1;
cout << "请输入第2个复数:";
int a2, b2;
cin >> a2 >> b2;
Complex c1(a1, b1), c2(a2, b2);
c1 == c2;
return 0;
}
重载双目运算符
双目运算重载为友元函数的定义格式
friend <返回值类型> operator #(<类型1> <参数1>, <类型2> <参数2>)
{ …… }
使用格式为:
<类型1> a;
<类型2> b;
a # b 或 operator#(a,b)
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
String() { p = NULL; }
String(char* str);
friend bool operator>(String& string1, String& string2);
friend bool operator<(String& string1, String& string2);
friend bool operator==(String& string1, String& string2);
void display();
private:
char* p;
};
String::String(char* str)
{
p = str;
}
void String::display()
{
cout << p;
}
bool operator>(String& string1, String& string2)
{
if (strcmp(string1.p, string2.p) > 0)
return true;
else return false;
}
bool operator<(String& string1, String& string2)
{
if (strcmp(string1.p, string2.p) < 0)
return true;
else return false;
}
bool operator==(String& string1, String& string2)
{
if (strcmp(string1.p, string2.p) == 0)
return true;
else return false;
}
int main()
{
String string1("Hello"), string2("Book"), string3("Computer");//vs2019不可行,待后续回归
cout << (string1 > string2) << endl;
cout << (string1 < string3) << endl;
cout << (string1 == string2) << endl;
return 0;
}
重载单目运算符
单目运算是指:只有一个操作数的运算,所以也称一元运算。如, !a , ++i ,j- - 等等。
单目运算符既可以重载为成员函数,也可以重载为类的友元函数。
单目运算符重载为成员函数的定义格式:
class <类名>
{ …
<返回值类型> operator # (); //运算符重载为成员函数
};
<返回值类型> <类名>::operator # () { … } //重载为成员函数的定义
使用格式:
<类名> a;
#a 或,a.operator#()//重载函数的调用
单目运算符重载为友元函数的定义格式:
定义格式
<返回值类型> operator #(<类型> <参数>) //运算符重载为友元函数的定义
{ …… }
使用格式为:
<类型> a;
#a 或 operator#(a) //重载函数的调用
典型单目运算符为“++” 或(- -)
它们分别有前置与后置两种
如果没有特殊说明
它们的前置用法与后置用法均使用同一个重载函数:
operator ++()
为了能够区分++(- -)的前置与后置用法
可为它们再写一个重载函数用于实现它们的后置用法
该重载函数应有一个形式上的int型参数:
operator ++(int);
以++运算为例,重载函数定义:
“++”为前置运算符,定义格式:
<类型><类名>::operator ++() { 函数体 }
“++”为后置运算符,定义格式:
<类型><类名>::operator ++(int) { 函数体 }
重载函数的调用格式:
前置“++”运算符,调用格式:
<操作对象>.operator ++();
后置“++”运算符,调用格式:
<操作对象>.operator ++(1);
#include <iostream>
using namespace std;
class Time
{
public:
Time() { minute = 0; sec = 0; }//默认构造函数
Time(int m, int s) { minute = m; sec = s; }//构造函数重载
Time operator++(); //声明运算符重载成员函数
void display()//定义输出时间函数
{
cout << minute << ":" << sec << endl;
}
private:
int minute;
int sec;
};
Time Time::operator++()
{
if (++sec >= 60)
{
sec = sec - 60;
++minute;
}
return *this;//返回自加后的当前对象
}
int main()
{
Time time1(34, 0);
for (int i = 0; i < 61; i++)
{
system("cls"); //清屏
++time1; time1.display();
}//如果改变显示方式为类似秒表方式
/*for (int i = 0; i < 61; i++)
{
++time1; time1.display();
}*/
return 0;
}
总结
对二元运算符,重载为成员函数时,仅一个参数,另一个被隐含;重载为友元函数时,有两个参数,没有隐含参数。
一般来说,一元运算符最好被重载为成员函数,对二元运算符最好被重载为友元函数。
练习
1.假定要对类 AB 定义减号操作符重载成员函数,实现两个 AB 类对象的减法,并返回相减结果,则该成员函数的声明语句为( )
A) AB operator-(AB &a ,AB &b);
B) AB operator-(AB &a ); ✔
C) operator-(AB a );
D) AB & operator-( );
2. 有如下的运算符重载函数定义:
double operator + (int i , int k) { return double (i+k); }
但定义有错误,对这个错误最准确的描述是?
A)+只能作为成员函数重载,而这里的+是作为非成员函数重载的
B)两个int型参数的和也应该是int型,而这里将+的返回值类型声明为double
C)没有将运算符重载函数声明为某个类的友元
D)C++已经提供了求两个int型数据之和的运算符+,不能再定义同样的运算符✔
3. 通过运算符重载,可以改变运算符原有的()
A)操作数类型✔
B)操作数个数
C)优先级
D)结合性
4. 在重载运算符时,其参数表中没有任何参数,这表明该运算符是()
A)作为友元函数重载的单目运算符
B)作为成员函数重载的单目运算符✔
C)作为友元函数重载的双目运算符
D)作为成员函数重载的双目运算符
个人实践
001
#include<iostream>
using namespace std;
class add
{public:
add() { x = 0, y = 0; }
add(int a, int b) :x(a), y(b) {}
friend add operator + (add& c1, add& c2)
{
add t;
t.x = c1.x + c2.x;
t.y = c1.y + c2.y;
return t;
}
void Display()
{
cout << "<"<<x<<","<<y<<">"<<endl;}
private:
int x,y;
};
int main()
{
int a, s, d, f;
cin >> a >> s >> d >> f;
add x1(a, s), x2(d, f), x3;
x3 = x1 + x2;
x1.Display();
x2.Display();
x3.Display();
}
实验二
#include<iostream>
using namespace std;
#define replace(i,x) for(int i=0;i<x;i++)
class Array
{
public:
Array();
Array(int* arr);
Array operator+(Array a);
void print_();
private:
int x[10];
};
Array::Array()
{
replace(i, 3)
x[i] = 0;
}
Array::Array(int arr[3])
{
replace(i, 3)
x[i] = *arr++;
}
Array Array::operator+(Array a)
{
Array t;
replace(i, 3)
t.x[i] = a.x[i] + x[i];
return t;
}
void Array::print_()
{
replace(i, 3)
cout << x[i] << " ";
cout << endl;
}
int main()
{
int a1[3], a2[3];
cout << "请输入两个一维数组(一维数组含三个元素),回车键隔开" << endl;
replace(i, 3)
cin >> a1[i];
replace(i, 3)
cin>> a2[i];
Array a(a1);
Array b(a2);
Array c = a + b;
c.print_();
}