#include<iostream>
using namespace std;
/*
*有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成
*员,这时可以将这些函数定义为该函数的友元函数。
*同类对象间无私处,异类对象间有友元
*除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行
*效率(即减少了类型检查和安全性检查等都需要实际开销),但它破坏了类的封装性
*和隐藏性,使得非成员函数可以访问类的私有成员。
*/
class A;
class B
{
public:
void dis(A & b);
};
class A
{
public:
A(int a=0,int b=0,int c=0)
:x(a),y(b),z(c)
{
}
friend void B::dis(A & b);
private:
int x;
int y;
int z;
};
/*
*如果是普通的,不能访问A类的私有数据
*所以要在类里面声明友元。如上
*友元函数写到哪里都可以,不受public和private的影响,但是为了习惯,
*比较我们private下面要写私有的,一般写到public里面
*函数可以成为友元,称为有元函数。函数是个全局函数,也可以是类函数
*/
#if 0
void dis(A & b)
{
cout<<b.x<<endl;
cout<<b.y<<endl;
cout<<b.z<<endl;
}
/*
*这里要注意的是,前向声明,是一种不完全型(forward declaration)声明
*即需要提供类名(无需提供类的实现)即可。这是因为是(incomplete type)功能也 很有限
*1.不能定义类的对象
*2.可以用于定义指向这个类型的指针或者引用
*用于声明(不是定义),使用该类型作为形参类型或者函数的返回值类型
*/
class B
{
public:
void dis(A &b)
{
cout<<b.x<<endl;
cout<<b.y<<endl;
cout<<b.z<<endl;
}
}
#endif
void B::dis(A &b)
{
cout<<b.x<<endl;
cout<<b.y<<endl;
cout<<b.z<<endl;
}
int main()
{
A a(1,2,3);
B b;
b.dis(a);
return 0;
}
/*
*友元关系不能被继承
*友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元
*要看在类中是否有相应的声明。
*友员关系不具有传递性,若类B是类A的友员,类C是类B的友员。类C不一定是
*类A的友员。同样要看类中是否有相应的声明
*/
#include<iostream>
#include<cmath>
using namespace std;
/*
*求两点之间的距离
*/
/*
class Point;
class Distance
{
public:
double getDistance(Point & a,Point &b);
};
class Point
{
public:
Point(double a=0,double b=0)
:x(a),y(b)
{
}
//friend double distance(Point &a,Point &b);
friend double Distance::getDistance(Point &a,Point &b);
private:
double x,y;
};
#if 0
#if 0
友员,全局函数的练习
其余的就是类函数的练习
double distance(Point &a,Point & b)
{
double dx=a.x-b.x;
double dy=b.x-b.y;
return sqrt(dx*dx+dy*dy);
}
int main()
{
Point a(4),b(9,5);
cout<<distance(a,b)<<endl;
return 0;
}
#endif
double Distance::getDistance(Point &a,Point &b)
{
double dx=a.x-b.x;
double dy=a.y-b.y;
return sqrt(dx*dx-dy*dy);
}
int main()
{
Point a(4),b(9,4);
Distance dt;
cout<<dt.getDistance(a,b)<<endl;
return 0;
}
#endif
*/
/*
*我们在来想一想,如果我们一个类里面有100个类函数,那么你要这么写100次
*那是不是太麻烦了,所以我们直接把类变成友元类。
*把一个类作为另一个类的友元,这就是友元类。
*/
class Point
{
public:
Point(double xx=0,double yy=0)
:x(xx),y(yy)
{
}
friend class Distance;
private:
double x;
double y;
};
class Distance
{
public:
double getDirectDistance(Point &a,Point &b)
{
double dx=a.x-b.x;
double dy=a.y-b.y;
return sqrt(dx*dx+dy*dy);
}
double getTriDistance(Point &a,Point &b)
{
double dx=a.x-b.x;
double dy=a.y-b.y;
return sqrt(dx*dx)+sqrt(dy*dy);
}
};
int main()
{
Point a(3,4),b;
Distance distance;
cout<<distance.getDirectDistance(a,b)<<endl;
cout<<distance.getTriDistance(a,b)<<endl;
return 0;
}
#include<iostream>
using namespace std;
/*
*友元还是成员
*假设我们有类Sender类和Mail类,实现发送邮件的功能
*Sender sender;Mail mail;
*sender<<mail;
*看到这里你想到下面几点
*1.两个类之间发生了关系,到底是什么关系呢,由一个运算符链接起来了
* 很明显<<这个东西被重载了。这个东西就涉及到一个问题。
* 这里就有两种情况,第一种是全局的。
* operator<<(sender,mail)
* sender.operator<<(mail)
* 第一种情况我们就先不做分析了,你sender是一个类,但是mail也是一个类
* 但是你sender有访问了mail,你凭访问,就要有友元了。
* 所以我们拿到了就应该知道operator<<应该做sender的友元函数,mail的成员函数
*
*/
class Mail;
class Sender
{
public:
Sender(string addr)
:_addr(addr)
{
}
Sender &operator<<(Mail mail);
private:
string _addr;
};
class Mail
{
public:
Mail(string time,string title,string contents)
:_time(time),_title(title),_contents(contents)
{
}
friend Sender & Sender::operator<<(Mail mail);
private:
string _time;
string _title;
string _contents;
};
Sender & Sender::operator<<(Mail mail)
{
cout<<mail._time<<endl;
cout<<mail._title<<endl;
cout<<mail._contents<<endl;
}
int main()
{
Sender sender("xxxxxx@qq.com");
Mail mail("2018:02:13:03:35","have a meeting","everyone need enjoy");
sender<<mail;
return 0;
}