在c++编程中,我们常常接触到类的概念,众所周知,一般类中有公用的(public)成员和私有的(private)成员,公用成员可以通过外部访问,私有成员只有奔雷中的函数才可以访问。今天小编将给大家介绍一个不遵循此规则的类,那就是友元(friend)。
C++中的友元是好友的意思,可以访问与其有好友关系的类中的私有成员,友元包括友元函数和友元类,下面我们就一起来看看他们的用法吧。
友元函数
在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 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 的。
现在由于声明了 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 类的私有成员变量了。
两点注意:
a. ddress类进行了提前声明,是因为在Address类定义之前、在Student类中使用到了它,如果不提前声明,编译会报错,提示"Address" has not been declared。类的提前声明和函数的提前声明是一个道理。
b. 中将 Student 类的声明和定义分开了,而将 Address 放在了中间,是因为 Student::display() 函数体中用到了 Address 类的成员,必须出现在 Address 类的类体之后(类体说明了有哪些成员)。
一般情况下,类必须在正式声明之后才能使用;但是某些情况下(如上例所示),只要做好提前声明,也可以先使用。但是应当注意,类的提前声明的使用范围是有限的。只有在正式声明一个类以后才能用它去创建对象。如果在上面程序第4行后面增加一行:
Address obj; //企图定义一个对象
会在编译时出错。因为创建对象时是要为对象分配内存空间的,在正式声明类之前,编译系统无法确定应该为对象分配多大的空间。编译器只有在“见到”类体后(其实是见到成员变量),才能确定应该为对象预留多大的空间。在对一个类作了提前引用声明后,可以用该类的名字去定义指向该类型对象的指针变量或对象的引用变量(如在本例中,定义了Address类对象的引用变量)。这是因为指针变量和引用变量本身的大小是固定的,与它所指向的类对象的大小无关。
请注意程序是在定义 Student::display() 函数之前正式声明 Address 类的。这是因为在 Student::display() 函数体中要用到 Address 类的成员变量 province、city、district,如果不正式声明 Address 类,编译器就无法识别这些成员变量。
c. 一个函数可以被多个类声明为“朋友”,这样就可以引用多个类中的私有成员。
友元类
不仅可以将一个函数声明为一个类的“朋友”,而且可以将整个类(例如B类)声明为另一个类(例如A类)的“朋友”。这时B类就是A类的友元类。
友元类B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。在A类的类体中用以下语句声明B类为其友元类:
friend B;
声明友元类的一般形式为:
friend 类名;
关于友元,有两点需要说明:
1、友元的关系是单向的而不是双向的。如果声明了 B类是A类的友元类,不等于A类是B类的友元类,A类中的成员函数不能访问B类中的私有数据。
2、友元的关系不能传递,如果B类是A类的友元类,C类是B类的友元类,不等于 C类是A类的友元类。
在实际开发中,除非确有必要,一般并不把整个类声明为友元类,而只将确实有需要的成员函数声明为友元函数,这样更安全一些。
以上就是c++中,友元函数和友元类的使用方法,还没有完全看明白的亲可以收藏,在某些时候,通过友元,我们可以更方便的实现某些功能。
推荐学习:《C++面向对象编程》http://www.maiziedu.com/course/qrs/379-3966/
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传