王桂林老师C++之友元
友元,英语为friend,朋友的意思,朋友就是关系亲密的两个人,能够分享物品的两个人。
由此可见,友元在C++之中的作用,就是实现数据的方便访问。
本文将从下面三个方面来阐述friend的功能:
- 在什么情况下,使用友元能够带来方便?
- 友元可以修饰哪几种类型?
- 友元注意事项?
在什么情况下,使用友元能够带来方便?
先举一个生活中的例子。A和B是借贷关系,每次A找B贷款,都需要得到B的同意,这样做很符合规矩。但是,有时候A频繁的找B借钱,这样B就频繁的接待A,很耽误自己的时间,而且也很麻烦。B就开始想办法解决这个麻烦,他觉得A值得信任,可以做他的朋友,于是就告诉A,以后你来找我借钱,就直接到一个地方拿,不需要经过我的允许。这样,麻烦就解决了。但是,也导致了不安全。
同样,在C++中,也是一样的道理。先定义一个类B:
//main.cpp
class B
{
public:
int getX()
{
return x;
}
private:
int x;
};
void func()
{
B b;
for (int i=0; i<10000; i++)
{
std::cout<<b.getX()<<std::endl; //只能通过接口访问类私有成员
}
}
因为类的私有成员不能直接被访问,所以func函数访问B中的x,就必须要经过B的公共成员函数getX。但是如果将func声明为B的友元,则就可以通过B的对象直接访问x。修改如下,
class B
{
public:
friend void func(B & b); //友元函数声明(注意:友元函数不受public、private的影响,一般习惯放在public下)
private:
int x;
};
//友元函数定义
void func(B & b)
{
for (int i=0; i<10000; i++)
{
std::cout<<b.x<<std::endl; //直接通过类对象访问私有成员
}
}
友元可以修饰哪几种类型?
从上一段中可以得知,全局函数可以成为类的友元。除了全局函数外,还有不同类的成员函数、类的对象都可以成为一个类的友元。
//A类的成员函数为B类的友元函数
//main.cpp
class B; //因为类A中使用了B的引用,所以必须要在类A之前进行这种不完全声明。(注意:不完全声明后,只能使用其引用和指针。)
class A
{
public:
int getadd(B & b);
};
class B
{
public:
friend int A::getadd(B & b); //格式基本与全局函数声明一致,只是函数前加上类命名空间
private:
int x;
int y;
};
int A::getadd(B & b)
{
return (b.x + b.y);
}
假如类A的所有成员函数,都是去操作类B的成员变量。为了方便,可以直接把A声明为B的友元,这样就不需要一个函数一个函数的声明了。
//A类为B类的友元函数
//main.cpp
class B;
class A
{
public:
int getadd(B & b);
int getsub(B & b);
};
class B
{
public:
friend A;
private:
int x;
int y;
};
int A::getadd(B & b)
{
return (b.x + b.y);
}
int A::getsub(B & b)
{
return (b.x - b.y);
}
友元注意事项?
- 友元关系不能够被继承。
- 友元关系是单向的,不具有交换性。如果类A是类B的友元,那么类B不一定是类A的友元,要看类中是否有相关的声明。
- 友元关系不具备传递性。如果类A是类B的友元,类C是类A的友元,那么类C不一定是类B的友元,要看类中是否有相关的声明。