由来
我们已知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。
为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
友元声明
友元声明出现于类体内,并向一个函数或另一个类授予对包含友元声明的类的私有及受保护成员的访问权。
- 友元关系不是相互的,除非显式指定。在上面的示例中,YourClass 的成员函数无法访问 YourOtherClass 的私有成员。
- 友元关系不能继承(你朋友的孩子不是你的朋友)。这意味着从 YourOtherClass 派生的类不能访问 YourClass 的私有成员。
- 友元关系不可传递(你朋友的朋友不是你的朋友)。因此 YourOtherClass 的友元类无法访问 YourClass 的私有成员。
- 友元声明中不能使用存储类说明符。在友元声明中定义的函数具有外部链接。先前已定义的函数保持其定义时所具有的连接
- 访问说明符对于友元声明的含义没有影响(它们可出现于 private: 或于 public: 节,且并无区别)
- 当局部类将一个无限定的函数或类声明为其友元时,只查找在其最内层非类作用域中的函数与类,而非全局函数:
class F {};
int f();
int main()
{
extern int g();
class Local { // main() 函数中的局部类
friend int f(); // 错误,没有声明于 main() 的该函数
friend int g(); // OK,main() 中有 g 的声明
friend class F; // 令局部 F(随后定义)为友元
friend class ::F; // 令全局 F 为友元
};
class F {}; // 局部 F
}
分类
友元函数
友元普通函数
- 友元函数是一个函数、它不是类的成员,但是可以访问类的私有和受保护成员
- 友元函数不被视为类成员,它们是获得了特殊访问权限的普通外部函数
- 友元不在类的范围内,并且不是使用成员选择运算符(
.
/->
)调用,除非它们是另一个类的成员 - friend 声明可放置在类声明中的任何位置。 它不受访问控制关键字的影响。
#include <iostream>
using namespace std;
class Point
{
friend void ChangePrivate( Point & ); // 随便放哪里声明都可以,只要在类里面就可以
public:
Point( void ) : m_i(0) {}
void PrintPrivate( void ){cout << m_i << endl; }
private:
int m_i;
};
void ChangePrivate ( Point &i ) { i.m_i++; }
int main(){
Point point;
point.PrintPrivate();
ChangePrivate(point);
point.PrintPrivate();
}
从上面我们可以看出,friend
函数有权访问类的私有对象成员
友元类成员函数
类成员函数可以视为其他类中的友元:
class B;
class A {
public:
int Func1( B& b );
private:
int Func2( B& b );
};
class B {
private:
int _b;
// A::Func1 is a friend function to class B
// so A::Func1 has access to all members of B
friend int A::Func1( B& );
};
int A::Func1( B& b ) { return b._b; } // OK
int A::Func2( B& b ) { return b._b; } // C2248
友元类
friend 类是类的所有成员函数都是类的友元函数的类,即,其成员函数可以访问另一个类的私有和受保护成员:
#include <iostream>
using namespace std;
class YourClass {
friend class YourOtherClass; // Declare a friend class
public:
YourClass() : topSecret(0){}
void printMember() { cout << topSecret << endl; }
private:
int topSecret;
};
class YourOtherClass {
public:
void change( YourClass& yc, int x ){yc.topSecret = x;}
};
int main() {
YourClass yc1;
YourOtherClass yoc1;
yc1.printMember();
yoc1.change( yc1, 5 );
yc1.printMember();
}
内联友元定义(这玩意有什么用啊)
(只允许在非局部类的定义中使用)定义一个非成员函数,同时令其为此类的友元。这种非成员函数始终为内联函数。
这种内联函数,类似于成员内联函数,其行为就像它们在所有类成员显示后但在类范围关闭前(类声明的结尾)被定义时的行为一样。 在类声明中定义的友元函数在封闭类的范围内。
class X {
int a;
friend void friend_set(X& p, int i) {
p.a = i; // 此为非成员函数
}
public:
void member_set(int i) {
a = i; // 此为成员函数
}
};
C++ public,protected,private 友元类有啥区别
- 没区别,友元是声明,跟位置无关