运算符重载
1 运算符重载函数的定义
运算符的重载实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该重载的运算符时调用此函数。这个函数叫做运算符重载函数,通常为类的成员函数。
定义运算符重载函数的一般格式:
返回值类型 类名::operator重载的运算符(参数表)
{……}
operator是关键字,它与重载的运算符一起构成函数名。因函数名的特殊性,C++编译器可以将这类函数识别出来。
2 运算符重载函数的参数
2.1 运算符重载函数为类的成员函数
当用类的成员函数实现运算符的重载时,运算符重载函数的参数(当为双目运算符时)为一个或(当为单目运算符时)没有。运算符的左操作数一定是对象,因为重载的运算符是该对象的成员函数,而右操作数是该函数的参数。
2.2 运算符重载函数为非成员函数
当用非成员函数实现运算符的重载时,运算符重载函数的参数为左右操作数
3 单目运算符++ --的重载
单目运算符“++”和“--”存在前置与后置问题。
前置“++”格式为:
返回类型 类名::operator++(){……}
而后置“++”格式为:
返回类型 类名::operator++(int){……}
后置“++”中的占位参数int仅用作区分,并无实际意义,可以给一个变量名,也可以不给变量名。
4 c++中不允许重载的运算符
5 友元函数
5.1 友元函数的说明
友元(friend)函数允许在类外访问该类中的任何成员,就象成员函数一样。友元函数用关键字friend说明
5.2 友元函数的特性
一个常规的成员函数声明描述了三件在逻辑上相互不同的事情
1、该函数能访问类声明的私用部分
2、该函数位于类的作用域之中
3、该函数必须经由一个对象去激活(有一个this指针)
通过将一个函数声明为友元可以使它只具有第一种性质
5.3 友元函数的说明点
- 友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员名。但友元函数可以访问类中的所有成员,一般函数只能访问类中的公有成员。
- 友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果一样。
- 某类的友元函数的作用域并非该类作用域。如果该友元函数是另一类的成员函数,则其作用域为另一类的作用域,否则与一般函数相同。
5.4 友元类
友元类:整个类可以是另一个类的友元。友元类的每个成员函数都是另一个类的友元函数,都可访问另一个类中的保护或私有数据成员。定义方法如下:
class A{……
friend class B; //声明B为A的友元类
…… };
6、单目运算符的重载及利用友元函数重载<<、>>
#include <iostream>
#include <string>
using namespace std;
class Int;
ostream& operator<<(ostream &out, const Int &d);
istream& operator>>(istream &in, Int &d);
class Int
{
friend ostream& operator<<(ostream &out, const Int &d);
friend istream& operator>>(istream &in, Int &d);
public:
Int(int d = 0) :data(d)
{
}
Int& operator++() // ++a
{
data++;
return *this;
}
Int operator++(int) // a++
{
Int tmp(data);
data++;
return tmp;
}
private:
int data;
};
ostream& operator<<(ostream &out, const Int &d)
{
out << d.data;
return out;
}
istream& operator>>(istream &in, Int &d)
{
in >> d.data;
return in;
}
int main()
{
Int d(10);
Int a;
a = d++; // a = 10 d = 11
cout << "a:" << a << endl;
cout << "d:" << d << endl;
a = ++d; // a = 12 d = 12
cout << "a:" << a << endl;
cout << "d:" << d << endl;
system("pause");
return 0;
}
一般都将<<、>>运算符的重载写作友元函数,若是重载为类的成员函数,在使用时需要将输入、输出流对象写在运算符的右边,不符合使用习惯
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
using namespace std;
class Int
{
public:
Int(int d = 0) :data(d)
{
}
ostream& operator<<(ostream &out)
{
out << data;
return out;
}
istream& operator>>(istream &in)
{
in >> data;
return in;
}
private:
int data;
};
int main()
{
Int d(10);
d << cout << endl;
d >> cin;
d << cout << endl;
}