友元
一般来说,类内的私有数据是对外不可见的,但在有些情况下,我们需要在类外对该类的私有数据进行访问,这就需要用到一种新技术——友元
(friend),即在声明前添加关键字friend
。
友元关系是单向的,即如果A是B的友元,但B不一定是A的友元;
友元关系无传递性,即如果A是B的友元,B是C的友元,但A不一定是C的友元。
1. 友元函数
友元函数是指某些非类成员函数,但可以访问类内的私有数据。
#include <iostream>
using namespace std;
class A {
private:
int data;
public:
A() : data(1) {}
friend void show( const A& t ); //添加friend定义友元函数
};
/* 友元函数在类外声明时不加friend */
void show( const A& t ) {
cout << "data = " << t.data << endl;
}
int main(void) {
A a;
show(a);
return 0;
}
/*
运行结果:
data = 1
*/
2. 友元类
友元类是指若需要在类B中直接访问类A的私有数据,因此将B作为A的友元(在A中声明friend class B;
)。
友元类中的成员函数、私有数据都可以在另一个类中被使用(即类B中可以直接使用类A的私有数据等)
class Tv {
private:
int state;
public:
friend class Remote; //声明Remote为Tv的友元类
enum{ Off, On };
Tv( int s = Off ) : state(s) {}
void onoff() { state = (state == On) ? Off : On; }
};
class Remote {
public:
void onoff( Tv & t ) { t.onoff(); }
};
3. 友元成员函数
友元成员函数是指类中的一个成员函数被定义为友元函数。
与友元类不同的是,只有友元成员函数可以在另一个中被使用,其余函数都不可以。
#include <iostream>
using namespace std;
class B; //前向声明
class A{
private:
int a;
public:
A() { a = 1; }
void print( B & b );
};
/* 示例位置1 */
class B{
private:
int b;
public:
B() { b = 6; }
void print() { cout << b << endl; }
friend void A::print( B & b ); //友元成员函数
};
/* 被定义为友元成员函数的函数必须在类外(另一个使用该函数的类后面)定义 */
void A::print( B & b ) {
cout << "b = " << b.b << endl;
}
int main() {
A a;
B b;
a.print( b );
return 0;
}
/*
输出结果:
b = 6
*/
需要注意的是:
(1)类的前向声明。由于在A中的print函数需要使用B,如果不进行B的前向声明,编译器就不知道B是一个类,会报错。
(2)类的排列顺序。在类B中会用到A的方法print(),因此需要先定义A,再定义B。
(3)友元成员函数的定义位置。友元成员函数不能使用内联代码,类中只能有函数声明。函数定义需要放到类之后,在类外进行定义,而且必须放到另一个类定义的后面。(对上面代码来说,若将A::print()的定义放在类B定义之前——示例位置1处,也会报错,提示类B未完成)
对于友元的位置在何处生明,可以简单记为friend在哪,哪个就可以被外面直接访问。(friend在类A,A就可以被其他特定位置访问)