第一篇、C++运算符重载
2012-11-20 09:39
155 查看
运算符重载
C++的运算符重载有两种情况:一种是使用成员函数重载,一种是非成员的友元函数重载。
这两种重载有时可以互用,但有时不能。
class complex
{
private:
double epart; //复数的实部
double ipart; //复数的虚部
public :
complex()
{
rpart+ipart+0.0; //缺省构造函数
}
complex(double rp,double ip)
{
rpart=rp;
ipart=ip;
}
complex
operator+(const complex&com)
{
complex temp(rpart+com.rpart,ipart+com.ipart);
return
temp;
}
};
这是简单的复数+运算符重载,这里是作为成员函数重载的,当然这里月可以用友元函数。
#include <iostream.h>
class Complex
{
public:
Complex()
{
real
= 0;
imag
= 0;
}
Complex(double
r, double i)
{
real
= r;
imag
= i;
}
friend
Complex operator + (Complex& c1, Complex& c2);
friend
Complex operator - (Complex& c1, Complex& c2);
friend
Complex operator - (Complex& c);
void print();
private:
double
real;
double
imag;
};
void Complex::print()
{
cout <<
"(" << real << ", " << imag << ")" << endl;
}
Complex operator + (Complex& c1, Complex& c2)
{
double
r = c1.real + c2.real;
double
i = c1.imag + c2.imag;
return
Complex(r, i);
}
Complex operator - (Complex& c1, Complex& c2)
{
double
r = c1.real - c2.real;
double
i = c1.imag - c2.imag;
return
Complex(r, i);
}
Complex operator - (Complex& c)
{
return
Complex(-c.real, -c.imag);
}
int main()
{
Complex
a(5, 4), b(1, 7);
Complex
c(0, 0);
c = a +
b;
c.print();
c = a -
b;
c.print();
c = -b;
c.print();
return
0;
}
这些一般的重载是没有问题的,但是有四个运算符是不能用友元重载的,=,->,(),[ ]这四个运算符不能用友元函数重载,至于为什么呢?
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
A(){x=99;}
A(int xx)
{
cout<<"Call A(int xx)"<<endl;
x = xx;
}
};
int main()
{
A a;
a = 7;
}
程序执行结果为:
Call A(int xx)
说明执行a = 7这程序语句时,程序去调用类A中的带参构造函数。
在类A中加入一赋值运算重载成员函数,如下:
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
A(){x=99;}
A(int xx)
{
cout<<"Call A(int xx)"<<endl;
x = xx;
}
A operator=(int xx) //重载赋值运算符运算
{
cout<<"Call A operator=(int xx)"<<endl;
x = xx;
return *this;
}
};
int main()
{
A a;
a = 7;
}
程序运行结果:
Call A operator=(int xx)
说明在类A中已经有相应赋值运算符重载函数的时候,执行赋值语句a = 7;程序会去调用类A中相应的赋值运算符重载函数,而不会像上面原来那
样去调用有参构造函数。
在此,我们可以对C++规则做出以下的判断:
当类中没有定义赋值运算符重载成员函数时(注意,在未定义形参数据类型为该类类型的赋值运算符重载函数时,编译器会自动生成加入),当
程序执行到某一赋值语句时,程序就会调用与赋值语句中右值类型匹配的构造函数,而把这右值当作此构造函数的实参。像最初的赋值语句a = 7
,执行时,实际做的操作是a(7)。而当类中有定义赋值运算符重载成员函数,执行赋值语句时,程序就只会去调用相应的赋值运算符重载函数。
当明白上面的规则后,现在就可以回过来,讨论为什么赋值运算符不可以重载为类的友元函数了。
我们知道友元函数不是类的成员函数,它只是类的“朋友“,具有访问把它声明为“朋友”的类的数据成员的权限而已。
那么当把赋值运算符重载为类的友员函数,在程序中执行类对象的赋值语句时,程序就会出现两种矛盾的选择。
1、因为它认为类中并没有重载赋值运算符的成员函数,所以它根据C++的规则,会去调用相应的构造函数。
2、但是在全局里,我们已经重载了参数类型为此类类型的赋值运算符函数,而这赋值语句刚好和这函数匹配上了,根据C++的规则,也会去调用
这函数。
程序是不允许有矛盾不确定选择的,所以当赋值运算符重载为类的友元函数时,编译器就会提示错误。
对于剩下的3个运算符 ->, [], () 为什么不能重载为友元函数,也是跟上面一样的道理。即编译器发现当类中没有定义这3个运算符的重载成员
函数时,就会自己加入默认的运算符重载成员函数。
例当类A中没有定义运算符->的重载成员函数,但是我们仍然可以对类A对象指针用->的形式调用指针指向的对象里的成员。像类A里有成员函数f
(),当
A a;
A* p = &a;
p->f(); //虽然类A中没有自己定义运算符->重载成员函数,但这里仍可这样使用
然而,当我们把->运算符重载为类A的友元函数时,程序就会出现跟把赋值运算符重载友元一样的情况,即产生矛盾性。
上面是不能重载为友元函数的情况,当然也有不能重载成成员函数的运算符。比如>>,<<这两个运算符:
#include <iostream>
using namespace std;
class test
{
private:
int i;
float f;
char ch;
public:
test(int a=0,float b=0,char c='\0'){i=a;f=b;ch=c;}
friend ostream &operator<<(ostream &,test);
friend istream &operator>>(istream &,test &);
};
ostream &operator <<(ostream &stream,test obj)
{
stream<<obj.i <<",";
stream<<obj.f<<",";
stream<<obj.ch<<endl;
return stream;
}
istream &operator >>(istream &t_stream,test &obj)
{
t_stream>>obj.i;
t_stream>>obj.f;
t_stream>>obj.ch;
return t_stream;
}
void main()
{
test A(45,8.5,'w');
operator <<(cout ,A);
test B,C;
cout<<"Input as i f ch:";
operator >>(cin,B);
operator >>(cin,C);
operator <<(cout ,B);
operator >>(cout,C);
}
友元流输入的标准声明应该是
friend std::istream& operator>>(std::istream& stm, test& obj);
流输入>>需要两个参数 第一个是流对象 第二个是要读取数据存放到的对象
因为你需要 stm >> a >> b这样的操作所以要返回stream本身的引用
这里必须使用友元,如果是类的成员函数重载,在main函数中调用时,一定是对象调用,如A>>(cin,B),但是<<,>>这两个运算符对应的是标准输入输出。
C++的运算符重载有两种情况:一种是使用成员函数重载,一种是非成员的友元函数重载。
这两种重载有时可以互用,但有时不能。
class complex
{
private:
double epart; //复数的实部
double ipart; //复数的虚部
public :
complex()
{
rpart+ipart+0.0; //缺省构造函数
}
complex(double rp,double ip)
{
rpart=rp;
ipart=ip;
}
complex
operator+(const complex&com)
{
complex temp(rpart+com.rpart,ipart+com.ipart);
return
temp;
}
};
这是简单的复数+运算符重载,这里是作为成员函数重载的,当然这里月可以用友元函数。
#include <iostream.h>
class Complex
{
public:
Complex()
{
real
= 0;
imag
= 0;
}
Complex(double
r, double i)
{
real
= r;
imag
= i;
}
friend
Complex operator + (Complex& c1, Complex& c2);
friend
Complex operator - (Complex& c1, Complex& c2);
friend
Complex operator - (Complex& c);
void print();
private:
double
real;
double
imag;
};
void Complex::print()
{
cout <<
"(" << real << ", " << imag << ")" << endl;
}
Complex operator + (Complex& c1, Complex& c2)
{
double
r = c1.real + c2.real;
double
i = c1.imag + c2.imag;
return
Complex(r, i);
}
Complex operator - (Complex& c1, Complex& c2)
{
double
r = c1.real - c2.real;
double
i = c1.imag - c2.imag;
return
Complex(r, i);
}
Complex operator - (Complex& c)
{
return
Complex(-c.real, -c.imag);
}
int main()
{
Complex
a(5, 4), b(1, 7);
Complex
c(0, 0);
c = a +
b;
c.print();
c = a -
b;
c.print();
c = -b;
c.print();
return
0;
}
这些一般的重载是没有问题的,但是有四个运算符是不能用友元重载的,=,->,(),[ ]这四个运算符不能用友元函数重载,至于为什么呢?
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
A(){x=99;}
A(int xx)
{
cout<<"Call A(int xx)"<<endl;
x = xx;
}
};
int main()
{
A a;
a = 7;
}
程序执行结果为:
Call A(int xx)
说明执行a = 7这程序语句时,程序去调用类A中的带参构造函数。
在类A中加入一赋值运算重载成员函数,如下:
#include <iostream>
using namespace std;
class A
{
private:
int x;
public:
A(){x=99;}
A(int xx)
{
cout<<"Call A(int xx)"<<endl;
x = xx;
}
A operator=(int xx) //重载赋值运算符运算
{
cout<<"Call A operator=(int xx)"<<endl;
x = xx;
return *this;
}
};
int main()
{
A a;
a = 7;
}
程序运行结果:
Call A operator=(int xx)
说明在类A中已经有相应赋值运算符重载函数的时候,执行赋值语句a = 7;程序会去调用类A中相应的赋值运算符重载函数,而不会像上面原来那
样去调用有参构造函数。
在此,我们可以对C++规则做出以下的判断:
当类中没有定义赋值运算符重载成员函数时(注意,在未定义形参数据类型为该类类型的赋值运算符重载函数时,编译器会自动生成加入),当
程序执行到某一赋值语句时,程序就会调用与赋值语句中右值类型匹配的构造函数,而把这右值当作此构造函数的实参。像最初的赋值语句a = 7
,执行时,实际做的操作是a(7)。而当类中有定义赋值运算符重载成员函数,执行赋值语句时,程序就只会去调用相应的赋值运算符重载函数。
当明白上面的规则后,现在就可以回过来,讨论为什么赋值运算符不可以重载为类的友元函数了。
我们知道友元函数不是类的成员函数,它只是类的“朋友“,具有访问把它声明为“朋友”的类的数据成员的权限而已。
那么当把赋值运算符重载为类的友员函数,在程序中执行类对象的赋值语句时,程序就会出现两种矛盾的选择。
1、因为它认为类中并没有重载赋值运算符的成员函数,所以它根据C++的规则,会去调用相应的构造函数。
2、但是在全局里,我们已经重载了参数类型为此类类型的赋值运算符函数,而这赋值语句刚好和这函数匹配上了,根据C++的规则,也会去调用
这函数。
程序是不允许有矛盾不确定选择的,所以当赋值运算符重载为类的友元函数时,编译器就会提示错误。
对于剩下的3个运算符 ->, [], () 为什么不能重载为友元函数,也是跟上面一样的道理。即编译器发现当类中没有定义这3个运算符的重载成员
函数时,就会自己加入默认的运算符重载成员函数。
例当类A中没有定义运算符->的重载成员函数,但是我们仍然可以对类A对象指针用->的形式调用指针指向的对象里的成员。像类A里有成员函数f
(),当
A a;
A* p = &a;
p->f(); //虽然类A中没有自己定义运算符->重载成员函数,但这里仍可这样使用
然而,当我们把->运算符重载为类A的友元函数时,程序就会出现跟把赋值运算符重载友元一样的情况,即产生矛盾性。
上面是不能重载为友元函数的情况,当然也有不能重载成成员函数的运算符。比如>>,<<这两个运算符:
#include <iostream>
using namespace std;
class test
{
private:
int i;
float f;
char ch;
public:
test(int a=0,float b=0,char c='\0'){i=a;f=b;ch=c;}
friend ostream &operator<<(ostream &,test);
friend istream &operator>>(istream &,test &);
};
ostream &operator <<(ostream &stream,test obj)
{
stream<<obj.i <<",";
stream<<obj.f<<",";
stream<<obj.ch<<endl;
return stream;
}
istream &operator >>(istream &t_stream,test &obj)
{
t_stream>>obj.i;
t_stream>>obj.f;
t_stream>>obj.ch;
return t_stream;
}
void main()
{
test A(45,8.5,'w');
operator <<(cout ,A);
test B,C;
cout<<"Input as i f ch:";
operator >>(cin,B);
operator >>(cin,C);
operator <<(cout ,B);
operator >>(cout,C);
}
友元流输入的标准声明应该是
friend std::istream& operator>>(std::istream& stm, test& obj);
流输入>>需要两个参数 第一个是流对象 第二个是要读取数据存放到的对象
因为你需要 stm >> a >> b这样的操作所以要返回stream本身的引用
这里必须使用友元,如果是类的成员函数重载,在main函数中调用时,一定是对象调用,如A>>(cin,B),但是<<,>>这两个运算符对应的是标准输入输出。
相关文章推荐
- 秒杀多线程第一篇 多线程笔试面试题汇总
- 第一篇博客
- 博客第一篇随笔
- 第一篇:fastadmin的页面是如何生成的?
- 第一篇博客写点什么呢。。。
- 《Qt学习之路--第一篇》串口通信
- 自学unity之人物动画控制(第一篇)
- 第一篇博客,写给自己!
- 自己动手写android手机桌面(第一篇)
- 【spring-boot神器】第一篇:拦截器,过滤器,监听器,控制器,消息转换器,AOP执行顺序
- Java图像处理最快技术:ImageJ 学习第一篇
- 第一篇博客
- 第一篇博客
- 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
- 五月学习笔记第一篇(Android下载代码)
- 第一篇:JAVA集合之ArrayList源码剖析
- 第一篇:优美的程序需要优美的子程序
- 第一篇——第四文 SQL Server 事务日志备份(连载中。。。。)
- 第一篇:可重入内置锁
- JAVA 第一篇