1.1为何需要友元
我们知道C++的类中访问权限分public,protected,private。当我们想通过类方法进行访问的时候往往是在public的区域写一个函数来访问。但是这种方式过于严格拉,所以C++就有了友元。
友元友元,就是类的好朋友,可以用用他的数据啦。
1.2举一个重载的例子说明其重要性
随手写的一个Time例子,在此类中重载了*号运算符,使*能让对象与一个int类的数相乘,使min变成原来的a倍,并且返回这个T类。
class T {
private:
int hours;
int minutes;
public:
T();
T(int h, int m=0);
void show() const;
T operator*(int a) const; //类内重载*号
};
T T::operator*(int a) const {
T cheng;
cheng.hours = this->hours;
cheng.minutes = this->minutes * a;
return cheng;
}
于是便可以愉快的调用啦,如下代码所示调用,可以发现time*3是对的,但三3*time是错的??
Why??为森么呢,在我们的直观感觉上,进行了重载*号,两个东西相乘,交换一下应该是没有区别的。但是C++并不是这样的!
记住:左侧的操作数应该是调用对象!左侧的操作数应该是调用对象!左侧的操作数应该是调用对象!
因此time*3这种表达对应于我们刚刚写的成员函数,time为调用对象,而3并不是调用对象!所以是错误的。
int main() {
T time(12,30);
T now(2,30);
T mm = time*3;//这样是对的
T nn = 3*time;//这样是错的哦
mm.show();
nn.show();
return 0;
}
1.3解决方法
如果按上面说的,我们重载了运算符但是也只能这样用,不能交换,其不是很麻烦?
我们当然可以告诉我们的程序员,我们必须按照 对象*数字 这种方式写,但这是一种服务器友好-客户警惕(server-friednly,client-beware)的解决方案。我们能不能遵从内心,用数字*对象这种方式写呢。答案是可以的。我们使用非成员函数。
class T {
private:
int hours;
int minutes;
public:
T();
T(int h, int m=0);
void show() const;
T operator*(int a) const; //
friend T operator*(double m,const T &t) ;//友元在类中声明一下,但是不属于类
};
T T::operator*(int a) const {
T cheng;
cheng.hours = this->hours;
cheng.minutes = this->minutes * a;
return cheng;
}
T operator*(double m,const T& t) //注意这里,这里的operator*并不是在T这个类空间中的
{
T temp;
temp.minutes = m*t.minutes;
return temp;
}
如上所示,我们就可以 T nn = 3*time了,这样做就会匹配到这个函数。是不是非常方便?
注意:1.友元函数只是在类中声明,因此在写定义的时候不要加类限定符。
2.同上,友元函数在类中声明,但并不属于他,不是成员函数,因此不能用成员运算符来调用他。