友元函数和友元类:
采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。
但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。
除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率,但又破坏了类的封装性,因为友元使得非成员函数可以访问类的私有成员。
从这一点来也可以看出,C++并不是纯的面向对象的语言,毕竟,C++语言的设计是为了实用,而不是追求理想的抽象。
一. 友元函数
1. 概念:
友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,
其格式如下:
friend 类型 函数名(形式参数);
形式参数必须是类对象的引用。
2. 说明:
(1) 友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。
(2) 一个函数可以是多个类的友元函数,不过需要在各个类中分别声明。
(3) 友元不是成员函数,但是它可以访问类中的私有成员。
(4) 友元函数常常是另一个类的一个成员函数,这样通过友元函数就可以使一个类对象直接访问另一个对象的私有成员。
再次强调,友元破坏了类的封装性
(5) 当友元函数是另一个类的成员函数时,应当注意以下几点:
A:友元函数作为一个类(如Boy)的成员函数时,除应当在它所在的类定义中声明之外,还应当在另一个类(如Girl)中声明它的友元关系,声明语句的格式为:
friend 函数类型 函数所在类名::函数名(参数列表);
B:友元函数(如disp)在引用本类对象(如b)的私有成员(如name,age)时无需本类对象的引用参数,但在引用声明它是友元的类(如Girl)的对象(如g)中的
私有成员(如name,age)时, 必须有友元类对象的引用参数。
C:一个类(如Boy)的成员函数作另一个类(如Girl)的友元函数时,必须先定义,而不是仅仅声明它。3. 举例:
(1)外部函数作为友无函数:
/* 例1:friend_person.cpp */
/* IDE环境: Dev-C++ 4.9.9.2 */
/* 外部函数作为友无函数 */
#include "stdio.h"
#include "string.h"
#define NAME_MAXLENGTH 20
class Person
{
public:
Person()
{
memcpy(name," NO Name",NAME_MAXLENGTH);
age = 0;
sex = 'W';
}
Person(char* n, int a, char s)
{
memcpy(name,n,NAME_MAXLENGTH);
age = a;
sex = s;
}
friend void disp(Person&); // 声明友元函数
char* getName()
{
return name;
}
~Person()
{
printf("destory: %s/n", this->getName());
}
private:
char name[NAME_MAXLENGTH];
int age;
char sex; // 'M': men; 'W': women
};
void disp(Person &x) // 定义外部友元函数,不是定义成员函数。
{
printf("name: %20s, ", x.name);
printf("age: %4d, ", x.age);
printf("sex: %2c ", x.sex);
printf("/n");
}
void testFunction()
{
Person Wang("Wang",20,'M');
disp(Wang); // 调用友元函数
}
int main()
{
testFunction();
while(1);
return 0;
}
运行结果:
/* result:
name: wang, age: 20, sex: M
destory: wang
*/
(2)另一个类的一个成员函数作为友无函数:
/* 例2:friend_Girl_Boy.cpp */
/* IDE环境: Dev-C++ 4.9.9.2 */
/* 另一个类的一个成员函数作为友无函数 */
#include <stdio.h>
#include <string.h>
class Girl; //向前引用, 声明类名Girl
class Boy{
private:
char *name;
int age;
public:
Boy(char *N,int A)
{
name=new char[strlen(N)+1];
strcpy(name,N);
age=A;
}
void disp(Girl &); //声明disp()为类boy的成员函数
~Boy(){delete name;}
};
class Girl{
private:
char *name;
int age;
public:
Girl(char *N,int A)
{
name=new char[strlen(N)+1];
strcpy(name,N);
age=A;
}
friend void Boy::disp(Girl &); //声明类Boy的成员函数disp()为类Girl的友元函数
~Girl(){delete name;}
};
void Boy::disp(Girl &x) // 定义成员友元函数
{
printf("Boy/'s name is: %s, age is: %d /n", name, age); //访问本类对象成员
printf("Girl/'s name is: %s, age is: %d /n", x.name, x.age); //访问友元类对象成员
}
int main()
{
Boy b("chen hao",25);
Girl g("zhang wei",18);
b.disp(g);
while(1);
return 0;
}
运行结果:
/* result:
Boy's name is: chen hao, age is: 25
Girl's name is: zhang wei, age is: 18
*/
二. 友元类
1. 定义友元类:
也可以把一个类而不仅仅是一个函数声明为另一个类的友元类。这时,只需先声明它而不一定需要先定义。
定义友元类的语句格式如下:
friend class 类名;
其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。
例如,以下语句说明类B是类A的友元类:
class A
{
…
public:
friend class B;
…
};
经过以上说明后,类B的所有成员函数都是类A的友元函数,且能存取类A的私有成员和保护成员。
2. 友元类注意事项:
(1) 友元关系是单向的,并且只在两个类之间有效。即使类X是类Y的友元,类Y是否是类X的友元也要看类X中是否有相应的声明。即友元关系不具有交换性。
(2) 若类X是类Y的友元,类Y是类Z的友元,也不一定就说明类X是类Z的友元,即友元关系也不具有传递性。
3. 举例:
/* 例3:friend_class.cpp */
/* IDE环境: Dev-C++ 4.9.9.2 */
/* 友元类 */
#include <stdio.h>
#include <string.h>
class Girl; //向前引用, 声明类名Girl
class Boy{
private:
char *name;
int age;
public:
Boy(char *N,int A)
{
name=new char[strlen(N)+1];
strcpy(name,N);
age=A;
}
void disp(Girl &); //声明disp()为类boy的成员函数
~Boy(){delete name;}
};
class Girl{
private:
char *name;
int age;
friend class Boy; //声明类boy是类Girl的友元, 在VC6.0中,可以省略"class",
//但是,在Dev-C++ 4.9.9.2中,"class"是不可以省略的。
public:
Girl(char *N,int A)
{
name=new char[strlen(N)+1];
strcpy(name,N);
age=A;
}
//friend void Boy::disp(Girl &); //声明类Boy的成员函数disp()为类girl的友元函数
~Girl(){delete name;}
};
void Boy::disp(Girl &x) // 定义函数disp()为类Boy的成员函数,也是类Girl的友元函数
{
printf("Boy/'s name is: %s, age is: %d /n", name, age); //访问本类对象成员
printf("Girl/'s name is: %s, age is: %d /n", x.name, x.age); //访问友元类对象成员
}
int main()
{
Boy b("chen hao",25);
Girl g("zhang wei",18);
b.disp(g);
while(1);
return 0;
}
运行结果:
/* result:
Boy's name is: chen hao, age is: 25
Girl's name is: zhang wei, age is: 18
*/
朋友的朋友是朋友。