运算符重载
运算符的重载实际上是通过函数重载实现的。
一般格式:
函数类型 operator 运算符名称(参数列表)
{对运算符的重载处理}
上面的重载格式中,“operator +”就是重载函数的函数名,意为对“+”运算符的重载函数
例如,想将"+"重载为对complex(复数)类的加法运算,函数原型可以为:
Complex operator + (Comples &c1, Complex &c2);
看一段代码😊
# include<iostream>
using namespace std;
class Complex
{
public:
int real;
int image;
Complex() //构造函数
{
real=0;
image=0;
}
Complex(int r, int i) //构造函数重载
{
real = r;
image = i;
}
Complex operator + (Complex &c1); //声明重载运算符的函数
};
Complex Complex::operator + (Complex &c1) //定义运算符重载函数
{
Complex c;
c.real= real + c1.real;
c.image = image + c1.image;
return c;
}
int main()
{
Complex c1(2,5),c2(4,6),c3;
c3=c1+c2;
cout<<"c1+c2="<<c3.real<<"+"<<c3.image<<"i"<<endl;
return 0;
}
运算符重载函数既可以作为成员函数也可以作为友元函数
上面那段代码是将运算符重载函数作为成员函数,下面则是作为友元函数
# include<iostream.h>
class Complex
{
public:
int real;
int image;
Complex() //构造函数
{
real=0;
image=0;
}
Complex(int r, int i) //构造函数重载
{
real = r;
image = i;
}
friend Complex operator + (Complex &c1,Complex &c2); //声明重载运算符的函数
};
Complex operator + (Complex &c1,Complex &c2) //定义运算符重载函数
{
Complex c;
c.real= c1.real + c2.real;
c.image = c1.image + c2.image;
return c;
}
int main()
{
Complex c1(2,5),c2(4,6),c3;
c3=c1+c2;
cout<<"c1+c2="<<c3.real<<"+"<<c3.image<<"i"<<endl;
return 0;
}
再看一段代码
# include<iostream.h>
class Complex
{
public:
int real;
int image;
Complex() //构造函数
{
real=0;
image=0;
}
Complex(int r, int i) //构造函数重载
{
real = r;
image = i;
}
friend Complex operator + (Complex &c1,Complex &c2); //声明重载运算符的函数,作为友元函数
Complex operator + (int &c1); //声明重载运算符的函数,作为成员函数
};
Complex operator + (Complex &c1,Complex &c2) //友元函数的定义
{
Complex c;
c.real= c1.real + c2.real;
c.image = c1.image + c2.image;
return c;
}
Complex Complex::operator + (int &i) //成员函数的定义
{
Complex c;
c.real= real + i;
c.image = image ;
return c;
}
int main()
{
Complex c1(2,5),c2(4,6),c3,c4;
int i=5;
c3=c1+c2;
cout<<"c1+c2="<<c3.real<<"+"<<c3.image<<"i"<<endl;
c4=c1+i;
cout<<"c1+c2="<<c4.real<<"+"<<c4.image<<"i"<<endl;
return 0;
}
上面这段代码对运算符“+”重载了两次,一次作为友元函数重载,一次作为成员函数重载。实现了Complex类与Complex类、Complex类和C++标准类型(int型)数据的相加
**重载时作为友元函数和成员函数的区别:**如果重载为友元函数,那么必须要在函数的形参列表中列出所有的操作数,如Complex operator + (Complex &c1,Complex &c2)
,而如果重载为成员函数,如Complex operator + (int &c1);
或Complex Complex::operator + (int &i)
虽然可以在函数的形参列表中省略一个参数,但是在运算符的左侧必须是Complex类的对象
即,如果重载为成员函数 Complex operator + (int &c1):
c2=c1+i; //正确
c2=i+c1; //错误,+左侧须为Complex类对象
如果重载为成员函数,但是在参数列表中不省略参数呢?
# include<iostream.h>
class Complex
{
public:
int real;
int image;
Complex() //构造函数
{
real=0;
image=0;
}
Complex(int r, int i) //构造函数重载
{
real = r;
image = i;
}
// friend Complex operator + (Complex &c1,Complex &c2); //声明重载运算符的函数,作为友元函数
Complex operator + (int &i, Complex &c2); //声明重载运算符的函数,作为成员函数
};
Complex Complex::operator + (int &i, Complex &c2) //成员函数的定义
{
Complex c;
c.real= c2.real + i;
c.image = image ;
return c;
}
int main()
{
Complex c1(2,5),c2(4,6),c3,c4;
int i=5;
// c3=c1+c2;
// cout<<"c1+c2="<<c3.real<<"+"<<c3.image<<"i"<<endl;
c4=c1+i;
cout<<"i+c1="<<c4.real<<"+"<<c4.image<<"i"<<endl;
return 0;
}
运行结果:
--------------------Configuration: project2 - Win32 Debug--------------------
Compiling...
project2.cpp
E:\CPP-learning\project2.cpp(18) : error C2804: binary 'operator +' has too many parameters
E:\CPP-learning\project2.cpp(38) : error C2676: binary '+' : 'class Complex' does not define this operator or a conversion to a type acceptable to the predefined operator
执行 cl.exe 时出错.
project2.exe - 1 error(s), 0 warning(s)
原因很简单:如果按照上面代码中的运算符重载方式,显然成员函数并没有访问类的数据成员,而是仅仅访问了外部变量,这与成员函数的作用相矛盾。因此编译错误,显示重载函数的形参列表中有太多的参数。
另外,究竟什么时候运算符应该重载为友元函数,什么时候重载为成员函数也是有规定的。
再看一个例子,重载“>”,使得通过">"可以比较两个字符串的大小。
先定义一个String类
# include<iostream>
using namespace std;
class String
{
public:
String()
{
p=NULL;
}
String(char *str);
void display();
private:
char *p;
};
String::String(char *str)
{
p = str;
}
void String::display()
{
cout<<p<<endl;
}
int main()
{
String str1("Hello"), str2("Book");
str1.display();
str2.display();
return 0;
}
加上运算符重载的代码
# include<iostream>
# include <string.h>
using namespace std;
class String
{
public:
String()
{
p=NULL;
}
String(char *str);
void display();
friend bool operator > (String &str1, String &str2);
private:
char *p;
};
bool operator > (String &str1, String &str2)
{
if (strcmp(str1.p,str2.p)>0)
return true;
else return false;
}
String::String(char *str)
{
p = str;
}
void String::display()
{
cout<<p<<endl;
}
int main()
{
char *p1 ="Hello", *p2 ="Book";
String str1(p1), str2(p2);
str1.display();
str2.display();
int b;
b= (str1 > str2)?1:0;
cout<<b<<endl;
return 0;
}
运行结果:
[Running] cd "e:\CPP-learning\" && g++ project2.cpp -o project2 && "e:\CPP-learning\"project2
project2.cpp: In function 'int main()':
project2.cpp:38:12: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
char *p1 ="Hello", *p2 ="Book";
^~~~~~~
project2.cpp:38:26: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
char *p1 ="Hello", *p2 ="Book";
^~~~~~
Hello
Book
1
注意:上面的代码在GCC编译器上运行是可以的,但是在VC++6.0上运行的话:
--------------------Configuration: project2 - Win32 Debug--------------------
Compiling...
project2.cpp
E:\CPP-learning\project2.cpp(21) : error C2248: 'p' : cannot access private member declared in class 'String'
E:\CPP-learning\project2.cpp(16) : see declaration of 'p'
E:\CPP-learning\project2.cpp(21) : error C2248: 'p' : cannot access private member declared in class 'String'
E:\CPP-learning\project2.cpp(16) : see declaration of 'p'
E:\CPP-learning\project2.cpp(42) : error C2593: 'operator >' is ambiguous
执行 cl.exe 时出错.
project2.exe - 1 error(s), 0 warning(s)
得改成这样:
# include<iostream>
# include <string.h>
using namespace std;
class String
{
public:
String()
{
p=NULL;
}
String(char *str);
void display();
friend bool operator > (String &str1, String &str2)
{
if (strcmp(str1.p,str2.p)>0)
return true;
else return false;
}
private:
char *p;
};
// bool operator > (String &str1, String &str2)
// {
// if (strcmp(str1.p,str2.p)>0)
// return true;
// else return false;
// }
String::String(char *str)
{
p = str;
}
void String::display()
{
cout<<p<<endl;
}
int main()
{
char *p1 ="Hello", *p2 ="Book";
String str1(p1), str2(p2);
str1.display();
str2.display();
int b;
b= (str1 > str2)?1:0;
cout<<b<<endl;
return 0;
}
运行结果:
Hello
Book
1
Press any key to continue
重载++ 先自增1使用自增1后的变量值
# include <iostream>
using namespace std;
class Time
{
public:
Time()
{
min=0;
sec=0;
}
Time(int m, int s):min(m),sec(s){}
Time operator ++(); //重载++
void display()
{
cout<<min<<":"<<sec<<endl;
}
private:
int min;
int sec;
};
Time Time::operator ++()
{
if (++sec>=60)
{ sec-=60;
min++;
}
return *this;
}
int main()
{
Time t1(12,35);
++t1;
t1.display();
return 0;
}
重载++,先使用变量值,再后自增
# include <iostream>
using namespace std;
class Time
{
public:
Time()
{
min=0;
sec=0;
}
Time(int m, int s):min(m),sec(s){}
Time operator ++(int); //重载++
void display()
{
cout<<min<<":"<<sec<<endl;
}
private:
int min;
int sec;
};
Time Time::operator ++(int)
{
Time temp = *this;
if (++sec>=60)
{ sec-=60;
min++;
}
return temp;
}
int main()
{
Time t1(12,35), t2;
t2=t1++;
t1.display();
t2.display();
return 0;
}
重载<<
# include <iostream>
using namespace std;
class Complex
{
public:
Complex()
{
real=0;
image=0;
}
Complex(int r, int i): real(r), image(i){}
friend ostream& operator << (ostream &, Complex &);
private:
int real;
int image;
};
ostream& operator << (ostream & cout, Complex & c1)
{
cout<<c1.real<<"+"<<c1.image<<"i"<<endl;
return cout;
}
int main()
{
Complex c1(3,5),c2(4,5);
cout<<c1<<c2<<endl;
return 0;
}
**注意:**在重载友元函数的定义中,必须要返回ostream类的形参对象名(此处为cout),不能自己再定义一个ostream cout1
然后 return cout
重载 >>运算符, 方法与重载<<运算符类似
参考文献:《C++程序设计》 谭浩强