对运算符语义的重新定义(即,在不同情况下对同样的运算符做不同的解释)
运算符函数:运算符可看作函数
operand1 op operand2 可理解为 op( operand1, operand2 )
a+b => +(a,b) => Add( a, b )
[ 二元运算符是一个具有两个参数的函数
一元运算符是一个具有一个参数的函数 ]
运算符重载的作用:用自然的方式使用用户自定义的类类型。
①与基本类型的使用风格一致;
②提高程序的可理解性
运算符重载的两种形式
1类成员运算符重载
2友元运算符重载
不能重载的运算符:
:: .* ?: . sizeof
类成员运算符重载
类型 类名::operator 运算符( 参数表 )
{
… // 运算符函数体
}
重载二元运算符时,成员运算符函数只需显式传递一个参数(即二元运算符的右操作数),而左操作数则是该类对象本身,通过this指针隐式传递。
c1 + c2 ;
c1.operator +(c2);
重载一元运算符时,成员运算符函数没有参数,操作数是该类对象本身,通过this指针隐式传递
-c1 ;
c1.operator - ( );
COMPLEX COMPLEX::operator + (const COMPLEX& other)
{
COMPLEX temp;
temp.real = real + other.real;
temp.image = image + other.image;
return temp;
}
赋值运算符的重载
若某个类没有重载赋值运算符,则编译器将自动生成一个缺省的赋值运算符,缺省赋值运算符采用浅复制策略,把源对象逐位地拷贝到目标对象:
c1 = c2 ;
不含指针成员的类使用缺省赋值运算符即可,含指针成员的类应重载赋值运算符,实现深复制策略
先释放指针原来指向的内存空间,然后再重新分配内存空间,最后再把需要拷贝的内容置入这个空间内。既避免了内存垃圾,也避免了指针重名。这就是深复制(deep copy)。
STRING& STRING::operator=(const STRING &another)
{
length = another.length;
if (buffer)
delete []buffer;
buffer = new char[length+1];
if (buffer!=NULL)
strcpy(buffer,another.buffer);
return *this;
}
下标运算符[ ]的重载
int& operator [ ] (int index) // 取向量元素
{ if ((index < 0) || (index > MAX_SIZE - 1)) {
cout << "Index out of bounds.\n";
exit(1);
}
return table[index];
}
友元(friend)
友元(friend)关系允许类的设计者选择出一组其他的类或函数,使得它们可以访问该类的私有和受保护成员。
在类的声明中,用friend声明的函数或类,即是该类的友元。
一个类的友元可以是:
游离函数(不属于任何类的函数)
另一个类其他类的成员函数。
友元关系破坏了类的封装性,不可滥用
游离函数作为友元
// 类VALUE中定义了一个友元函数set(),注意set()不是该类的成员函数
class VALUE
{
public:
//声明set()为VALUE的友元
friend void set(VALUE obj, int x);
private:
int value;
};
void set(VALUE obj, int x) // 实现友元函数set()
{
obj.value = x; // set()可以象VALUE成员函数一样访
// 问obj的私有和受保护成员
}
另一个类作为友元
class Y; // Y类的引用性声明
class X {
public:
// 把Y类声明为X类的友元,则Y类的所有成员函数都是X的友元
friend Y;
private:
int k ;
void m_Xfunc( );
};
class Y {
public:
void m_Yfunc( X& obj );
};
void Y::m_Yfunc( X& obj )
{
obj.k = 100 ; // Y类的成员函数是X的友元,可以访问X的私有和受保护成员
}
其它类的成员函数作友元
class Y {
public:
void Yfunc( );
};
class X {
public:
friend void Y::Yfunc( ); // 把Y类的Yfunc函数声明为X类的友元
private:
int k ;
void m_Xfunc( );
};
void Y::Yfunc( )
{
X obj;
obj.k = 100 ; // 该函数是X的友元,可以访问X的私有和受保护成员
}
Input/Output Overload
ostream& operator <<(ostream& out, const Fruit& x);
istream& operator >>(istream& in, Fruit& x);
ostream& operator << ( ostream& out, const Fruit& x)
{
out << "name: " << x.name
<< " color: " <<x.color << endl;
return out;
}
istream& operator >> (istream& in, Fruit& x)
{
cout << "Please enter the name: " << endl;
in >> x.name;
cout << "Please enter the color: " << endl;
in >> x.color;
return in;
}
Increment/decrement Overload
COMPLEX & operator++(); //重载前置++
COMPLEX operator++(int); //重载后置++
COMPLEX & operator--(); //重载前置--
COMPLEX operator--(int); //重载后置--
COMPLEX& COMPLEX::operator++() //COMPLEX.CPP
{
real += 1;
image += 1;
return *this;
}
COMPLEX COMPLEX::operator++(int)
{
COMPLEX before = *this;
real += 1;
image += 1;
return before;
}