一、操作符重载
用户定义的多个名称相同但特征标(参数列表)不同的函数,这被称为函数重载或函数多态。目的是让您能够用相同的函数来完成相同的基本操作,即使这种操作被用于不同的数据类型。
要重载操作符,需要使用被称为操作符函数的特殊函数形式,操作符函数的格式如下:
operator op (argument list)
操作符重载的限制:
1、重载后的操作符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符。
2、使用操作符时不能违反操作符原来的句法规则。例如,不能将求模操作符(%)重载成使用一个操作数。也不能修改操作符的优先级。
3、不能定义新的操作符。
4、不能定义下面的操作符:sizeof、成员操作符、作用域解析操作符、条件操作符等等。
5、下面的操作符只能通过成员函数进行重载:=、()、[]、->。
二、友元函数
通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
为什么需要友元呢,在为类重载二元操作符时(带两个参数的操作符)常常需要友元,特别是当重载的操作符函数的第一个参数不是调用对象时,因为成员函数必须由对象调用,此时就需要另外一种解决方式--非成员函数,非成员函数不是由对象调用的,它使用的所有值(包括对象)都是显式参数的。
对于非成员重载操作符函数来说,操作符表达式左边的操作数对应于操作符函数的第一个参数,操作符表达式右边的操作数对应于操作符函数的第二个参数,使用非成员函数可以按所需的顺序获得操作数,但引发了一个新问题:非成员函数不能直接访问类的私有数据,至少常规非成员函数不能访问,但是,有一类特殊的非成员函数可以访问类的私有成员,它们被称为友元函数。
创建友元函数的第一步是将其原型放在类声明中,并在其原型声明前加上关键字friend。
第二步是编写函数定义,因为它不是成员函数,所以不要使用作用域限定符,另外不要在定义中使用关键字friend。
提示:
1、如果要为类重载操作符,并将非类的项作为其第一个操作数,则可以用友元函数来反转操作数的顺序。
2、非成员版本的重载操作符函数所需的形参数目与操作符使用的操作数数目相同,而成员版本所需的参数数目少一个,因为其中的一个操作数是被隐式的传递的调用对象。
操作符重载示例:
要求:复数由两个部分组成,实数部分和虚数部分,复数的一种书写方式是:(3.0, 4.0),其中,3.0是实数部分,4.0是虚数部分,假设a=(A, Bi),c=(C, Di),则下面是一些复数运算:
加法:a + c = (A+C, (B+D)i)。
减法:a - c = (A-C, (B-D)i)。
乘法:a * c = (A*C-B*D,(A*D + B*C)i)。
乘法:x*c = (x*C, x*Di),其中x为实数。
共轭:~a = (A,-Bi)。
示例程序:
1、头文件complex0.h:
#ifndef _COMPLEX_H_
#define _COMPLEX_H_
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(int a, int b);
Complex();
~Complex();
Complex operator +(const Complex &a);
Complex operator -(const Complex &a);
Complex operator *(const Complex &a);
friend Complex operator *(const int a, const Complex &b);
Complex operator ~();
friend std::ostream & operator <<(std::ostream &os, const Complex &a);
friend std::istream & operator >>(std::istream &is, Complex &a);
private:
int real;
int imaginary;
};
#endif
2、定义文件complex0.cpp
#include "complex0.h"
Complex::Complex(int a, int b)
{
real = a;
imaginary = b;
}
Complex:: Complex()
{
real = 0;
imaginary = 0;
}
Complex::~Complex()
{
}
Complex Complex::operator +(const Complex &a)
{
return Complex(real+ a.real, imaginary + a.imaginary);
}
Complex Complex::operator -(const Complex &a)
{
return Complex(real - a.real, imaginary - a.imaginary);
}
Complex Complex::operator *(const Complex &a)
{
return Complex(real * a.real - imaginary * a.imaginary, real * a.imaginary + imaginary * a.real);
}
Complex operator *(const int a, const Complex &b)
{
Complex temp;
temp.real = a * b.real;
temp.imaginary = a * b.imaginary;
return temp;
}
Complex Complex::operator ~()
{
return Complex(real, -imaginary);
}
std::ostream & operator <<(std::ostream &os, const Complex &a)
{
os << "( " << a.real << ", " << a.imaginary << "i )" << endl;
return os;
}
std::istream & operator >>(std::istream &is, Complex &a)
{
cout << "Please enter real and imaginary: " << endl;
is >> a.real >> a.imaginary;
return is;
}
3、测试程序main.cpp
#include <iostream>
#include "complex0.h"
using namespace std;
int main(int argc, char * argv [ ])
{
Complex a (3.0, 4.0);
Complex c;
cout << "Enter a complex number(q to quit): \n";
while (cin >> c)
{
cout << "c is" << c << "\n";
cout << "complex conjugate is " << ~c << "\n";
cout << "a is " << a << "\n";
cout << "a + c is " << a + c << "\n";
cout << "a - c is " << a - c << "\n";
cout << "a * c is " << a * c << "\n";
cout << "2 * c is " << 2 * c << "\n";
cout << "Enter a complex number(q to quit): \n";
}
cout << "Done!";
return 0;
}
总结:
一般来说,访问私有类成员的唯一方法是使用类方法。C++使用友元函数来避开这种限制。要让函数成为友元,需要在类声明中声明该函数,并在声明前加上关键字friend。
C++扩展了对操作符的重载,允许自定义特殊的操作符函数,这种函数描述了特定的操作符与类之间的关系,操作符函数可以是类成员函数,也可以是友元函数(有一些操作符函数只能是类成员函数)。要调用操作符函数,可以直接调用该函数,也可以以通常的句法使用被重载的操作符。