一、友元函数的作用
函数的私有和保护变量在类内可以访问,在类外只可访问公有变量;派生类在类内只可访问其基类的公有变量和保护变量,在类外只可访问其公有变量(要看具体的继承类型);
因此,在有些情况下,需要访问类的私有或保护变量时,不得不调用其成员函数,因为只有成员函数才有访问的权限。因而多出许多时间开销。
友元函数和类的成员函数的访问权限相同,但是其不是类的成员函数,它破坏了类的封装性;友元函数分为三类:普通的友元函数,友元类,和类的成员函数成为友元函数;
因为友元函数没有this指针,则参数要有三种情况:
2.1.1 要访问非static成员时,需要对象做参数;
2.1.2 要访问static成员或全局变量时,则不需要对象做参数;
2.1.3 如果做参数的对象是全局对象,则不需要对象做参数;
(1)普通友元函数:常用的就是运算符重载
#include <iostream>
using namespace std;
class time
{
friend ostream& operator<<(ostream&,time& t);
private:
int x;
int y;
int z;
public:
time(int a,int b,int c):x(a),y(b),z(c){};
};
ostream& operator<<(ostream& out,time& t)
{
out<<"("<<t.x<<t.y<<t.z<<")";
return out;
}
int main()
{
time t(1,2,3);
cout<<t<<endl;
return 0;
}
友元函数的位置是无关紧要的;
(2)友元类
#include <iostream>
using namespace std;
class A;
class time
{
friend ostream& operator<<(ostream&,time& t);
private:
int x;
int y;
int z;
public:
time(int a,int b,int c):x(a),y(b),z(c){};
friend A;
};
class A
{
private:
int m;
int n;
public:
void test(time& t);
};
void A::test(time& t)
{
m=t.x;
n=t.y;
}
ostream& operator<<(ostream& out,time& t)
{
out<<"("<<t.x<<t.y<<t.z<<")";
return out;
}
int main()
{
time t(1,2,3);
cout<<t<<endl;
A a;
a.test(t);
return 0;
}
使用单个声明使A类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类A的对象可以具有类A和类time的功能
(3)类A的一个成员函数成为类B的友元函数
#include <iostream>
using namespace std;
class time;
class A
{
private:
int m;
int n;
public:
void test(time& t);
};
class time
{
friend void A::test(time& t);
friend ostream& operator<<(ostream&,time& t);
private:
int x;
int y;
int z;
public:
time(int a,int b,int c):x(a),y(b),z(c){};
};
void A::test(time& t)
{
m=t.x;
n=t.y;
}
ostream& operator<<(ostream& out,time& t)
{
out<<"("<<t.x<<t.y<<t.z<<")";
return out;
}
int main()
{
time t(1,2,3);
cout<<t<<endl;
A a;
a.test(t);
return 0;
}
注意: 此时类A的定义一定要在类time之前,此时test()函数的声明在类time之前,方为正确的,若在之后定义,则test()即使声明为友元函数,依然无法访问其私有变量;
ps:刚刚写的时候,利用头文件和cpp文件进行封装,在操作符重载函数前加了个inline 即
inline ostream& operator<<(ostream& out,time& t)
{
return out<<"("<<t.x<<t.y<<t.z<<")";
}
将它放在了cpp文件中,总是报错,后将其和头文件放在一起,就没有错误了;