C++语言基础(15)-友元函数和友元类
一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员。现在,我们来介绍一种例外情况——友元(friend)。借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。
一.将全局函数声明为友元函数
例:
#include <iostream>
using namespace std; class Student{
public:
Student(char *name, int age, float score);
public:
friend void show(Student *pstu); //将show()声明为友元函数
private:
char *m_name;
int m_age;
float m_score;
}; Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ } // 全局函数
void show(Student *pstu){
cout<<pstu->m_name<<"的年龄是 "<<pstu->m_age<<",成绩是 "<<pstu->m_score<<endl;
} int main(){
Student stu("小明", , 90.6);
show(&stu); //调用友元函数
Student *pstu = new Student("李磊", , 80.5);
show(pstu); //调用友元函数 return ;
}
运行结果:
小明的年龄是 15,成绩是 90.6
李磊的年龄是 16,成绩是 80.5
注意:友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。下面的写法是错误的:
void show(){
cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
}
二.将其它类的成员函数声明为友元函数
#include <iostream>
using namespace std; class Address; //提前声明Address类 //声明Student类
class Student{
public:
Student(char *name, int age, float score);
public:
void show(Address *addr);
private:
char *m_name;
int m_age;
float m_score;
}; //声明Address类
class Address{
private:
char *m_province; //省份
char *m_city; //城市
char *m_district; //区(市区)
public:
Address(char *province, char *city, char *district);
//将Student类中的成员函数show()声明为友元函数
friend void Student::show(Address *addr);
}; //实现Student类
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"区"<<endl;
} //实现Address类
Address::Address(char *province, char *city, char *district){
m_province = province;
m_city = city;
m_district = district;
} int main(){
Student stu("小明", , 95.5f);
Address addr("陕西", "西安", "雁塔");
stu.show(&addr); Student *pstu = new Student("李磊", , 80.5);
Address *paddr = new Address("河北", "衡水", "桃城");
pstu -> show(paddr); return ;
}
运行结果:
小明的年龄是 16,成绩是 95.5
家庭住址:陕西省西安市雁塔区
李磊的年龄是 16,成绩是 80.5
家庭住址:河北省衡水市桃城区
注意:
1.程序刚开始对Address类进行提前声明的意义在于:在Address类定义之前,在Student类中使用了它,如果不提前声明,编译器会报错:'Address' has not been declared'
2.程序将 Student 类的声明和实现分开了,而将 Address 类的声明放在了中间,这是因为编译器从上到下编译代码,show() 函数体中用到了 Address 的成员 province、city、district,如果提前不知道 Address 的具体声明内容,就不能确定 Address 是否拥有该成员(类的声明中指明了类有哪些成员)。
3.类的提前声明的使用范围是有限的,只有在正式声明一个类以后才能用它去创建对象。如果在上面程序的第4行之后增加如下所示的一条语句,编译器就会报错:
Address addr; //企图使用不完整的类来创建对象
4. 一个函数可以被多个类声明为友元函数,这样就可以访问多个类中的 private 成员。
三.友元类
可以将整个类声明为友元类,这样友元类中的所有成员函数都是另一个类的友元函数。
修改上述代码:
#include <iostream>
using namespace std; class Address; //提前声明Address类 //声明Student类
class Student{
public:
Student(char *name, int age, float score);
public:
void show(Address *addr);
private:
char *m_name;
int m_age;
float m_score;
}; //声明Address类
class Address{
public:
Address(char *province, char *city, char *district);
public:
//将Student类声明为Address类的友元类
friend class Student;
private:
char *m_province; //省份
char *m_city; //城市
char *m_district; //区(市区)
}; //实现Student类
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"区"<<endl;
} //实现Address类
Address::Address(char *province, char *city, char *district){
m_province = province;
m_city = city;
m_district = district;
} int main(){
Student stu("小明", , 95.5f);
Address addr("陕西", "西安", "雁塔");
stu.show(&addr); Student *pstu = new Student("李磊", , 80.5);
Address *paddr = new Address("河北", "衡水", "桃城");
pstu -> show(paddr); return ;
}
将Student类声明为Address类的友元类的语句为:
friend class Student;
有的编译器也可以不写 class 关键字,不过为了增强兼容性还是建议写上。
注意:
1.友元的关系是单向的而不是双向的。如果声明了类 B 是类 A 的友元类,不等于类 A 是类 B 的友元类,类 A 中的成员函数不能访问类 B 中的 private 成员。
2.友元的关系不能传递。如果类 B 是类 A 的友元类,类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。
C++语言基础(15)-友元函数和友元类的更多相关文章
- 【C++基础 05】友元函数和友元类
友元是一种定义在类外部的普通函数或类,但它须要在类体内进行说明,为了与该类的成员函数加以差别,在说明时前面加以keywordfriend. 友元不是成员函数,可是它能够訪问类中的私有成员. 友元的作用 ...
- 友元(友元函数、友元类和友元成员函数) C++
有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员. 友元(frend)机制允许一个类将 ...
- C++ friend友元函数和友元类(转)
一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员.现在,我们来介绍一种例外情 ...
- C++友元(友元函数、友元类和友元成员函数)
友元(友元函数.友元类和友元成员函数) C++ 有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私 ...
- C++学习12 友元函数和友元类
友元函数和友元类在实际开发中较少使用,想快速学习C++的读者可以跳过本节. 一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有 ...
- C++:友元(非成员友元函数、成员友元函数、友元类)
3.8 友元:友元函数和友元类 友元函数 :既可以是不属于任何类的非成员函数,也可以是另一个类的成员函数,统称为友元函数.友元函数不是当前类的成员函数,而是独立于类的外部函数,但它可以访问该类所有的 ...
- c++友元函数与友元类
友元函数和友元类的需要: 类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的.非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这 ...
- 第二十三节:Java语言基础-详细讲解函数与数组
函数 函数在Java中称为方法,在其他语言中可能称为函数,函数,方法就是定义在类中具有特定功能的程序.函数,在Java中可称为方法. 函数的格式: 修饰符 返回值类型 函数名(参数类型 参数1, 参数 ...
- 2.19 C++友元函数和友元类
参考: http://www.weixueyuan.net/view/6350.html 总结: 借助friend关键字将其声明为友元函数,结果,在display函数体内,我们就能访问private属 ...
随机推荐
- Annotation的语法和使用
http://blog.csdn.net/cdl2008sky/article/details/6265742 (1) .<context:component-scan base-package ...
- 【左偏树】BZOJ2809-[APIO2012]dispatching
[题目大意] 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同 ...
- [TC-HouseProtection]House Protection
题目大意: 一个平面直角坐标系中有给定的$n(n\le50)$个红点和$m(m\le50)$个蓝点,每个点可以选择画一个半径为$r$(所有的$r$相同)的圆或不画.圆的半径上限为$R(R\le1000 ...
- Problem Y: 零起点学算法21——摄氏温度转换
#include<stdio.h> int main() { float f,c; while(scanf("%f",&f)!=EOF) c=*(f-); pr ...
- 更新升级10.11 cocoapods安装出问题最简单的解决方法
这是因为10.11把cocoapods直接干掉了 sudo gem install -n /usr/local/bin cocoapods 再加一句,完美解决 sudo xcode-select -- ...
- 制作推送证书 and Code=3000 "未找到应用程序的“aps-environment”的权利字符串"
制作推送证书 step1. 打开苹果开发者网站 step2. 从Member Center进入Certificates, Identifiers & Profiles step3. 选择要制作 ...
- linux内核3.6版本及以下的bug引发的故障--cpu使用率100%
现象: 旗舰店运价库cpu使用率100%,load升高,导致后续的请求失败. 重启服务器,cpu.load恢复正常. 触发条件: (1)linux内核3. ...
- 通俗解释遗传算法及其Matlab实现
早上再看一个APP推荐的文章,发现的. (1)初识遗传算法 遗传算法,模拟达尔文进化论的自然选择和遗传学机理的生物进化过程的计算模型,一种选择不断选择优良个体的算法.谈到遗传,想想自然界动物遗传是怎么 ...
- 2017年最全的30个Android面试题,你将如何回答?
百度首页 登录 2017年最全的30个Android面试题,你将如何回答? 机翼技术 百家号 03-10 02:32 “三金四银”又是一年一度的跳槽季,相信有不少Android程序员开始摩拳擦掌蠢蠢欲 ...
- Centos:mysql的安装和使用:yum方式
1.安装: 安装客户端 sudo yum install mysql 安装服务器 sudo yum install mysql-server 2.配置:查看配置文件 cat /etc/my.cnf 3 ...