友元类
有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率
(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员
。
友元除了前面讲过的函数以外,友元还可以是类,即一个类可以作另一个类的友元。当一个类作为另一个类的友元时,这就意味着这个类的所有成员函数都是另一个类的友元函数
。
友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下:
friend 类型 函数名(形式参数);
使用友元类时注意:
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明
总结起来:
(1)友元关系不可以继承,但对已有的方法来说访问权限不改变。
(2)如果改写基类的方法则访问权限改变
(3)友元关系不具有传递性;若类B是类A的友元,类C是B的友元,类C不一定是类A的友元。
友元类的使用:
#include <iostream>
using namespace std;
class CObj
{
public:
CObj() : mX(0), mY(0) {}
friend class CFriend;
private:
void PrintData() const
{
cout << "mX = " << mX << endl
<< "mY = " << mY << endl;
}
int mX;
int mY;
};
class CFriend
{
public:
CFriend(int x, int y)
{
mObj.mX = x; //直接调用类CObj的私有数据成员
mObj.mY = y;
}
void ShowData() const
{
mObj.PrintData(); //直接调用类CObj的私有成员函数
}
private:
CObj mObj;
};
int main()
{
CFriend one(3, 4);
one.ShowData();
return 0;
}
执行结果:
mX = 3
mY = 4
友元函数的使用:
#include <iostream>
#include <string>
using namespace std;
class ca; //事先申明ca类,确保cb类的定义不出错
class cb { //在ca类之前定义cb类,确保在ca类里申明cb的test()作友元时不出错
public:
void test(ca& a); //由于ca类事先申明,这儿不出错
};
class ca {
string id;
void setId(string s) {
id = s;
}
protected:
string name;
void setName(string s) {
name = s;
}
public:
void print() {
cout << id << " " << name << " " << endl;
}
friend void cb::test(ca& a); //申明cb类的test()函数作友元,允许它访问私有保护成员
};
void cb::test(ca& a) { //作友元的成员函数的实装必须在ca类的后面,否则ca类的成员就未定义了。
a.id = "123"; //这是ca类的私有成员
a.setName("abc"); //这是ca类的保护成员
}
int main ( )
{
ca a;
cb b;
b.test(a);
a.print();
return 0;
}
执行结果:
123 abc