一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员。现在,我们来补充介绍一个例外——友元(friend)。
fnend 的意思是朋友,或者说是好友,与好友的关系显然要比一般人亲密一些。有的家庭可能会这样处理:客厅对所有来客开放,而卧室除了本家庭的成员可以进人以外,还允许好朋友进入。在C++中,这种关系以关键宇 friend 声明,中文多译为友元。友元可以访问与其有好友关系的类中的私有成员,友元包括友元函数和友元类。如果您对友元这个名词不习惯,可以按原文 friend 理解为朋友即可。
友元函数
在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。友元函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数。
友元函数可以访问当前类中的所有成员,包括 private 属性的。
1) 将普通函数声明为友元函数。
#include<iostream> using namespace std; class Student{ private: char *name; int age; float score; public: Student(char*, int, float); friend void display(Student &); //将display声明为友元函数 }; Student::Student(char *name, int age, float score){ this->name = name; this->age= age; this->score = score; } //普通成员函数 void display(Student &stu){ cout<<stu.name<<"的年龄是 "<<stu.age<<",成绩是 "<<stu.score<<endl; } int main(){ Student stu("小明", 16, 95.5f); display(stu); return 0; }
运行结果:
小明的年龄是 16,成绩是 95.5
请注意 display 是一个在类外定义的且没有使用 Student 作限定的函数,它是非成员函数,不属于任何类,它的作用是输出学生的信息。如果在 Student 类中未声明 display 函数为 friend 函数,它是不能引用 Student 中的私有成员 name、age、score 的。大家可以亲测一下,将上面程序中的第11行删去,观察编译时的信息。
现在由于声明了 display 是 Student 类的 friend 函数,所以 display 可以使用 Student 中的私有成员 name、age、score。但注意在使用这些成员变量时必须加上对象名,不能写成:
cout<<name<<"的年龄是 "<<age<<",成绩是 "<<score<<endl;
因为 display 不是 Student 类的成员函数,默认不能使用 Student 类的成员,必须指定要访问的对象。
2) 将其他类的成员函数声明为友元函数
friend 函数不仅可以是普通函数(非成员函数),还可以是另一个类中的成员函数。请看下面的例子:
#include<iostream> using namespace std; class Address; //对Address类的提前引用声明 //声明Student类 class Student{ private: char *name; int age; float score; public: Student(char*, int, float); void display(Address &); }; //声明Address类 class Address{ private: char *province; char *city; char *district; public: Address(char*, char*, char*); //将Student类中的成员函数display声明为友元函数 friend void Student::display(Address &); }; Address::Address(char *province, char *city, char *district){ this->province = province; this->city = city; this->district = district; } //声明Student类成构造函数和成员函数 Student::Student(char *name, int age, float score){ this->name = name; this->age= age; this->score = score; } void Student::display(Address &add){ cout<<name<<"的年龄是 "<<age<<",成绩是 "<<score<<endl; cout<<"家庭住址:"<<add.province<<"省"<<add.city<<"市"<<add.district<<"区"<<endl; } int main(){ Student stu("小明", 16, 95.5f); Address add("陕西", "西安", "雁塔"); stu.display(add); return 0; }
运行结果:
小明的年龄是 16,成绩是 95.5 家庭住址:陕西省西安市雁塔区
在本例中定义了两个类 Student 和 Address。程序第 26 行将 Student 类中的成员函数 display 声明为友元函数,由此,display 就可以访问 Address 类的私有成员变量了。
两点注意:
① 程序第4行对Address类进行了提前声明,是因为在Address类定义之前、在Student类中使用到了它,如果不提前声明,编译会报错,提示"Address" has not been declared。类的提前声明和函数的提前声明是一个道理。
② 程序中将 Student 类的声明和定义分开了,而将 Address 放在了中间,是因为 Student::display() 函数体中用到了 Address 类的成员,必须出现在 Address 类的类体之后(类体说明了有哪些成员)。
这里简单介绍一下类的提前声明。一般情况下,类必须在正式声明之后才能使用;但是某些情况下(如上例所示),只要做好提前声明,也可以先使用。
但是应当注意,类的提前声明的使用范围是有限的。只有在正式声明一个类以后才能用它去创建对象。如果在上面程序第4行后面增加一行:
Address obj; //企图定义一个对象
会在编译时出错。因为创建对象时是要为对象分配内存空间的,在正式声明类之前,编译系统无法确定应该为对象分配多大的空间。编译器只有在“见到”类体后(其实是见到成员变量),才能确定应该为对象预留多大的空间。在对一个类作了提前引用声明后,可以用该类的名字去定义指向该类型对象的指针变量或对象的引用变量(如在本例中,定义了Address类对象的引用变量)。这是因为指针变量和引用变量本身的大小是固定的,与它所指向的类对象的大小无关。
请注意程序是在定义 Student::display() 函数之前正式声明 Address 类的。这是因为在 Student::display() 函数体中要用到 Address 类的成员变量 province、city、district,如果不正式声明 Address 类,编译器就无法识别这些成员变量。
③ 一个函数可以被多个类声明为“朋友”,这样就可以引用多个类中的私有成员。
友元类
不仅可以将一个函数声明为一个类的“朋友”,而且可以将整个类(例如B类)声明为另一个类(例如A类)的“朋友”。这时B类就是A类的友元类。
友元类B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。在A类的类体中用以下语句声明B类为其友元类:
friend B;
声明友元类的一般形式为:
friend 类名;
关于友元,有两点需要说明:
友元的关系是单向的而不是双向的。如果声明了 B类是A类的友元类,不等于A类是B类的友元类,A类中的成员函数不能访问B类中的私有数据。
友元的关系不能传递,如果B类是A类的友元类,C类是B类的友元类,不等于 C类是A类的友元类。
在实际开发中,除非确有必要,一般并不把整个类声明为友元类,而只将确实有需要的成员函数声明为友元函数,这样更安全一些。
主要内容:友元函数,友元类在 C++ 中,一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员。现在,我们来介绍一种例外情况——友元(friend)。 借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。 friend 的意思是朋友,或者说是好友,与
C++ 类 & 对象 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。 友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。 如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 frien
本文向大家介绍剖析C++编程中friend关键字所修饰的友元函数和友元类,包括了剖析C++编程中friend关键字所修饰的友元函数和友元类的使用技巧和注意事项,需要的朋友参考一下 在某些情况下,为不是类成员的函数或单独类中的所有函数授予成员级别的访问权会更方便。仅类实现器可以声明其友元。函数或类不能将其自身声明为任何类的友元。在类声明中,使用 friend 关键字和非成员函数名称或其他类,以允许其
类的友元函数(friendfunetlon)在类范围之外定义,但有权访问类的 private(和第9章“继承”介绍的受保护)成员。函数或整个类都可以声明为另一个类的友元。 利用友元函数能提高性能,这里将介绍一个友元函数的例子。本书后面要用友元函数通过类对象和生成迭代类来重载运算符。迭代类对象用于连续选择项目或对容器类(见7.9节)对象中的项目进行操作。容器类对象能够存放项目。成员函数无法进行某些操
本文向大家介绍C++友元(Friend)用法实例简介,包括了C++友元(Friend)用法实例简介的使用技巧和注意事项,需要的朋友参考一下 相对于Java而言,友元是C++中特有的一种元素,很多教材上对其介绍的相对较少,因此初学的时候往往不能很快掌握,本文总结了友元的用法和一些注意的地方,供大家参考借鉴。希望能对初学C++的朋友起到一点帮助作用。 操作步骤: 1)在MyFriend类中,将Fath
我想知道如果函数的模板参数包括但不限于类的模板参数,如何使函数成为类的朋友并在类外定义函数。 例如,我有以下模板类和模板朋友函数: 如果我编译: 我会得到以下链接器错误: