友元
友元是一种允许非类成员函数访问类的非公有成员的一种机制。可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元,使得函数、类获得其私有和保护成员的访问权限。友元可以简化对私有和保护成员的访问,因为如果没有友元,可能需要提供一些额外的函数来访问这些成员。同时,因为友元是直接访问成员,而不是通过函数,在某种程度上提高了程序的运行效率。
友元函数
友元函数在类作用域外定义,但它需要在类体中进行说明。为了与该类的成员函数加以区别,定义的方式是在类中用关键字friend说明该函数,格式如下。
friend 类型 友元函数名(参数表);
友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员名。但友元函数可以访问类中的所有成员(公有的、私有的、保护的),一般函数只能访问类中的公有成员。友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果一样。某类的友元函数的作用域并非该类作用域。如果该友元函数是另一类的成员函数,则其作用域为另一类的作用域,否则与一般函数相同。友元函数破坏了面向对象程序设计类的封装性,所以友元函数如不是必须使用,则尽可能少用。或者用其他手段保证封装性。下面是一个具体的例子。
class A;
class B{
public:
void printA(A& a);
};
class A{
friend void printA(A& a);
friend void B::printA(A& a);
public:
A(int val):val_(val){}
private:
int val_;
};
void B::printA(A& a){
cout<<"A.val_ = "<<a.val_<<endl;
}
void printA(A& a){
cout<<"A.val_ = "<<a.val_<<endl;
}
需要注意的是,只有当一个类的定义已经被看到时它的成员函数才能被声明为另一个类的友元。这并不总是能够做到的。这里就需要先定义B,在定义A,并且,由于先定义了B,需要把A前向声明,然后访问A的私有成员时,发现这个函数需要能够看到A的定义,只能放到外面去。所以,把一个类函数声明为另一个类的友元函数的情况比较少见,并且有时候是做不到的,这时候可以把一个类定义为另一个类的友元类。
友元类
如果某类B的成员函数会频繁的存取另一个类A的数据成员, 而A的数据成员的Private/Protectd限制造成B存取的麻烦, B只能通过A的Public的成员函数进行间接存取。把B做成A类的友元类,即A类向B类开放其Private/Protectd内容, 让B直接存取。友元类,一个类可以作另一个类的友元;友元类的所有成员函数都是另一个类的友元函数友元类的声名如下。
friend class 类名;
下面是一个例子。
class B;
class A{
friend class B;
public:
A(int val):val_(val){}
private:
int val_;
};
class B{
public:
void printA(A& a){
cout<<"A.val_ = "<<a.val_<<endl;
}
};
友元类有以下值得注意的点:
- 友元关系是单向的。
- 友元关系不能被传递。
- 友元关系不能被继承。