实验目的
学习并掌握C++运算符类外重载即友元函数相关的内容
实验内容
在C++中,类的友元函数定义在类外部,但它有权访问类的所有私有成员(private)和保护成员(protected)。
尽管友元函数的原型有在类的定义中出现过,但友元函数和成员函数并不相同。
为什么要使用友元函数?
我们来看这样一种情况,对于两个类,A和B,A显然可以允许B的函数访问A的公有成员,但若是想要B的函数也可以访问A的私有成员,显然不借助其他手段是无法做到的。
这个时候,就需要友元函数。
友元函数的使用
如果一个类想把一个函数作为它的友元,只需要增加一条friend关键字开始的函数声明语句即可。如下:
#include <iostream>
using namespace std;
class num
{
public:
num operator+(const num& y)
{
num temp;
temp.lenth=this->lenth+y.lenth;
temp.width=this->width+y.width;
return temp;
}
num operator-(const num& y)
{
num temp;
temp.lenth=this->lenth-y.lenth;
temp.width=this->width-y.width;
return temp;
}
num operator*(const num& y)
{
num temp;
temp.lenth=this->lenth*y.lenth;
temp.width=this->width*y.width;
return temp;
}
num operator/(const num& y)
{
num temp;
temp.lenth=this->lenth/y.lenth;
temp.width=this->width/y.width;
return temp;
}
num operator=(const num& y)
{
int ss=y.lenth;
cout<<"使用了重载后的=运算符,右值的lenth为"<<ss<<endl;
this->width=y.width;
this->lenth=y.lenth;
return *this;
}
int lenth;
int width;
friend void printt(const num& y);
private:
double height=11.2;
};
void printt(const num& y)
{
cout<<"访问私有成员,height:"<<y.height<<endl;
}
int main()
{
num z;
printt(z);
}
因为printt是类num的友元函数,所以它可以访问num对象的私有成员height;
重载<<运算符
通过友元函数重载"<<"运算符,可以使得<<输出类的对象的属性只需要
cout<<z<<endl;
如上图
但仅仅如此还是不够的,试想下面一种情况
这样是不行的,这和我们之前讲过的类内重载=运算符的情况颇为相似,因为我们前面定义的<<重载仅仅是输出类的属性,却不能返回一个os对象,这使得它后面跟着其他内容即
cout<<z<<"其他内容";
这样时,<<无法识别左值z,那么就无法正常调用原来的<<运算符输出z后面的内容,我们只需要按照原来<<运算符的格式,将的返回值类型设置为一个ostream的引用即可(为什么返回值使用引用在上一篇文章已经介绍过,这里不再重复),这样就能正常调用原来的<<运算符了,如下
下面是完整代码
#include <iostream>
using namespace std;
class num
{
public:
num operator+(const num& y)
{
num temp;
temp.lenth=this->lenth+y.lenth;
temp.width=this->width+y.width;
return temp;
}
num operator-(const num& y)
{
num temp;
temp.lenth=this->lenth-y.lenth;
temp.width=this->width-y.width;
return temp;
}
num operator*(const num& y)
{
num temp;
temp.lenth=this->lenth*y.lenth;
temp.width=this->width*y.width;
return temp;
}
num operator/(const num& y)
{
num temp;
temp.lenth=this->lenth/y.lenth;
temp.width=this->width/y.width;
return temp;
}
num operator=(const num& y)
{
int ss=y.lenth;
cout<<"使用了重载后的=运算符,右值的lenth为"<<ss<<endl;
this->width=y.width;
this->lenth=y.lenth;
return *this;
}
int lenth;
int width;
friend void printt(const num& y);
friend ostream& operator<<(ostream & os, const num& y);
private:
double height=11.2;
};
void printt(const num& y)
{
cout<<"访问私有成员,height:"<<y.height<<endl;
}
ostream& operator<<(ostream & os, const num& y)
{
os<<"width:"<<y.width<<",length:"<<y.lenth<<endl;
return os;
}
int main()
{
num z;
printt(z);
z.lenth=12;
z.width=13;
cout<<"z的属性:"<<z<<endl;;
}
实验结论
经过这次实验,我们掌握了类外重载的用法,它和类内重载的区别在于它不是类的成员函数,而是仅仅在类内做一个友元声明,在类外定义,这样它就能访问类的私有成员了