您的位置:首页 > 编程语言 > C语言/C++

第一篇、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),但是<<,>>这两个运算符对应的是标准输入输出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: