(1) 对已有的运算符赋予多重含义
(2) 必要性:C++预定义的运算符运算对象只能是基本数据类型,而不适用于用户自定义类型(如 类)
(3) 实现机制:
(1) 可以重载的运算符:
上述运算符中,[ ] 是下标运算符,()是函数调用运算符,++和 – 是自增自减运算符包括前置后置形式。
另外,有4个运算符不能重载,即 长度运算符 sizeof、条件运算符 ?:、成员选择符== . == 和域解析运算符== : : == 。
(2) 其他规则
声明形式:
函数类型 operator 运算符(形参)
{
函数体;
}
重载为友元函数时,参数个数=原操作数个数-1 (后置++、–除外)。
(1) 双目运算符
如果重载运算符B 为类成员函数,使之能实现表示式oprd1 B oprd2, 其中oprd1位 A类对象,则 B 可被重载为 A 类的成员函数,形参类型是 oprd2 所属类型。经重载过,表达式 oprd1 B oprd2 相当于oprd1.operator B(oprd2)
举例说明:
重载 + 、+=,实现复数类complex 对象想相加。
#include
using namespace std;
class complex
{
public:
complex(double real = 0.0, double image = 0.0)
{ this->real = real;this->image = image;}
complex operator + (complex &c1); // 重载 + 为成员函数
void operator += (complex &c1); //重载 +=
int showComplex(); //输出复数
private:
double real;
double image;
};
complex complex::operator + (complex &c1) //重载 + 为成员函数的实现
{
/*complex c; //实现1:创建一个局部变量
c.real = c1.real + real;
c.image = c1.image + image;
return c;
*/
return complex(c1.real + real, c1.image + image); //实现2:创建临时变量,直接一句代码返回结果
}
void complex::operator+=(complex &c1) //重载 +=
{
real += c1.real;
image += c1.image;
}
int complex::showComplex()
{
cout << real;
if (image > 0)
cout << "+";
if (image != 0)
cout << image << "i" << endl;
return 0;
}
int main()
{
complex c1(1, 2), c2(-3, 4), c3;
cout << "c1=";c1.showComplex();
cout << "c2=";c2.showComplex();
c3 = c1 + c2; //重载+ 的使用,两边都为complex对象
cout << "c3=c1+c2=";c3.showComplex();
c2 += c1;//重载+= 的使用,两边都为complex对象
cout << "c2+=c1结果: ";c2.showComplex();
return 0;
}
(2) 前置单目运算符
如果要重载 U 为类成员函数,使之能够实现表达式 U oprd,其中 oprd 为A类对象,则 U 可被重载为 A 类的成员函数,无形参。经重载后,表达式 U oprd 相当于 oprd.operator U()
(3) 后置单目运算符 ++和–
复习一下++ 、–
示例 | 解释 |
---|---|
++i | i自增1后再参与运算;i的值加1,++i的值也加1 |
i++ | i参与运算后,i的值再加1;i的值加1,i++的值不变 |
如果要重载 ++或–为类成员函数,使之能够实现表达式 oprd++ 或 oprd-- ,其中 oprd 为A类对象,则 ++或-- 可被重载为 A 类的成员函数,且具有一个 int 类型形参。经重载后,表达式 oprd++ 相当于oprd.operator ++(0)
举例说明(1):
++ 实现Point类的坐标自增
#include
using namespace std;
class Point
{
private:
int x, y;
public:
Point(int x, int y)
{
this->x = x;
this->y = y;
}
Point() {}
Point & operator++();//重载前置单目运算符++为成员函数 ++i i加1,i++整体值加1
Point operator++(int);//重载后置单目运算符++成员函数 i++ 只有i加1,i++值不变
void showPoint();
};
Point & Point::operator++ () //++前置 原来的点变,x,y变
{
++x;
++y;
return *this;
}
Point Point::operator++(int) //后置++ 原来的点不变,x,y加1
{
Point old = (*this); //将旧对象放在新对象里,末尾返回旧对象
x++;
y++;
return old;
}
void Point::showPoint() {
cout << "(" << x << "," << y << ")" << endl;
}
int main() {
Point p1(1, 2), p2(3, 4), p3, p4;
p3 = ++p1; //++前置
p3.showPoint(); //(2,3)
p4 = p2++; //后置++
p4.showPoint(); //(3,4)
return 0;
}
举例说明(2):
++ 实现时间的自增
#include
using namespace std;
class Clock {
private:
int Hour, Minute, Second;
public:
Clock(int NewH = 0, int NewM = 0, int NewS = 0);
void ShowTime();
Clock operator ++();// 前置单目运算符重载
Clock operator++(int);//后置单目运算符重载
};
Clock::Clock(int NewH, int NewM, int NewS) {
Hour = NewH;
Minute = NewM;
Second = NewS;
}
Clock Clock::operator++() // 前置单目运算符重载
{
Second++;
if (Second >= 60)
{
Second = Second - 60;
Minute++;
if (Minute >= 60)
{
Minute = Minute - 60;
Hour++;
Hour = Hour % 24;
}
}
cout << "++Clock:";
return *this;
}
Clock Clock::operator++(int) // 后置单目运算符重载
{
Clock old = *this;
Second++;
if (Second >= 60)
{
Second = Second - 60;
Minute++;
if (Minute >= 60)
{
Minute = Minute - 60;
Hour++;
Hour = Hour % 24;
}
}
cout << "Clock++:";
return old;
}
void Clock::ShowTime()
{
cout << Hour << ":" << Minute << ":" << Second << endl;
}
int main() {
Clock myclock(23, 59, 59);
cout << "First clock:";
myclock.ShowTime();
(++myclock).ShowTime();
(myclock++).ShowTime();
return 0;
}
声明形式:
friend 函数类型 operator 运算符(形参)
{
函数体;
}
重载为友元函数时 , 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。
(1) 运算符友元函数的设计
双目运算符 B 重载后,表达式:oprd1 B oprd2 等同于:operator B(oprd1,oprd2)
前置单目运算符 B重载后,表达式:B oprd 等同于:operator B(oprd)
后置单目运算符 ++和–重载后,表达式:oprd B 等同于:operator B(oprd,0)
举例说明(1):
+、-、=、+=重载为友元函数 ,以complex类举例
#include
using namespace std;
class complex //复数类声明
{
public:
complex(double real = 0.0, double image = 0.0) { this->real = real; this->image = image; } //构造函数
friend complex operator + (complex c1, complex c2); //运算符+ 重载为友元函数
friend complex operator - (complex c1, complex c2); //运算符- 重载为友元函数
friend bool operator==(const complex &c1, const complex &c2);
friend complex operator += (complex &c1,complex &c2); //运算符+= 重载为友元函数
void showComplex(); //显示复数的值
private:
double real;
double image;
};
complex operator+(complex c1, complex c2)
{
return complex(c2.real + c1.real, c2.image + c1.image);
}
complex operator-(complex c1, complex c2)
{
return complex(c1.real - c2.real, c1.image - c2.image);
}
bool operator==(const complex &c1, const complex &c2) {
if (c1.real == c2.real && c1.image == c2.image) {
return true;
} else {
return false;
}
}
complex operator+=(complex &c1, complex &c2)
{
c1.real += c2.real;
c1.image += c2.image;
}
void complex::showComplex()
{
cout << real;
if (image > 0)
cout << "+";
if (image != 0)
cout << image << "i" << endl;
}
int main()
{
complex c1(1, 2), c2(-3, 4), c3, c4;
cout << "c1=";c1.showComplex();
cout << "c2=";c2.showComplex();
c3 = c1 + c2;
cout << "c3=c1+c2=";c3.showComplex();
c4 = c1 - c3;
cout << "c4=c1-c3=";c4.showComplex();
if(c4==c1){
cout << "c4==c1"<<endl;
}
return 0;
}
举例说明(2):
c1+c2, c1+i, i+c1
#include
using namespace std;
class complex
{
public:
complex(double real = 0.0, double image = 0.0)
{this->real = real;this->image = image;}
void show();
friend complex operator + (complex&c1, complex&c2);
friend complex operator + (complex&c1, int c2);
friend complex operator + (int c1, complex&c2);
private:
double real;
double image;
};
complex operator + (complex&c1, complex&c2)
{
complex c;
c.real = c1.real + c2.real;
c.image = c1.image + c2.image;
return c;
}
complex operator + (complex&c1, int c2)
{
complex c;
c.real = c1.real + c2;
c.image = c1.image;
return c;
}
complex operator + (int c1, complex&c2)
{
complex c;
c.real = c2.real + c1;
c.image = c2.image;
return c;
}
void complex::show()
{
cout << "(" << real << " + " << image << "i" << ")"<<endl;
}
int main()
{
complex c1(1, 2),c2(3,4),c3,c4,c5;
int i = 2;
cout << "i=" << i << endl;
cout << "c1=";c1.show();
cout << "c2=";c2.show();
c3 = c1 + c2;
cout << "c3=c1+c2=";c3.show();
c4 = c1+i;
cout << "c4=c1+i=";c4.show();
c5 = i + c1;
cout << "c5=i+c1=";c5.show();
return 0;
}
(1) 下标运算符[ ] 重载为成员函数
该重载函数在类中的声明格式:
返回值类型 & operator[](参数);
const 返回值类型 & operator[](参数) const;
使用第一种声明方式,[ ]不仅可以访问元素,还可以修改元素;
使用第二种声明方式,[ ]只能访问而不能修改元素;
在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应 const 对象,因为通过 const 对象只能调用 const 成员函数,如果不提供第二种形式,那么将无法访问 const 对象的任何元素;
#include
#include
using namespace std;
class MyString {
public:
MyString();//默认构造函数
MyString(const char*const); //构造函数
MyString(const MyString&);//复制构造函数
~MyString();//析构函数
char & operator[](int n); //成员函数重载[],该形式可修改可访问元素
char operator[](int n)const;//常成员函数重载[],用于const对象调用
int getLen()const { return length;}
const char *getMyString()const {return myString;}
private:
char *myString;
int length;
};
MyString::MyString() { //默认构造函数
myString = new char[1];
myString[0] = '\0';
length = 0;
}
MyString::MyString(const char *const str) { //构造函数
length = strlen(str);
myString = new char[length + 1];
for (int i = 0;i < length;i++)
myString[i] = str[i];
myString[length] = '\0';
}
MyString::MyString(const MyString &str) { //复制构造函数
length = str.getLen();
myString = new char[length + 1];
for (int i = 0;i < length;i++)
myString[i] = str[i];
myString[length] = '\0';
}
MyString::~MyString() { //析构函数
delete[]myString;
length = 0;
}
char & MyString::operator [](int n) { //下标运算符[]重载
if (n > length | n < 0)
cout << "数组下标越界!" << endl;
else
return myString[n];
}
char MyString::operator [](int n)const
{
if (n > length | n < 0)
cout << "数组下标越界!" << endl;
else
return myString[n];
}
int main() {
MyString str1("xiaobencong zhen shuai!");
cout << "str1: " << str1.getMyString() << endl;
cout << "str1[4]: " << str1[4] << endl;
cout << "str1[-1]: " << str1[-1] << endl;
cout << "str1[99]:" << str1[999] << endl;
return 0;
}
(2) 关于 什么时候用友元函数和成员函数,大家可以阅读这篇文章:
C++ 运算符重载
欢迎关注微信公众号:学编程的金融客,作者:小笨聪