MyException - 我的异常网
当前位置:我的异常网» C++ » C++中的友元总结

C++中的友元总结

www.MyException.Cn  网友分享于:2013-10-09  浏览:2次
C++中的友元小结

我们知道,在一个类总可以有公有的(public)成员和私有的(private)成员。在类外可以访问公用成员,只有本类中的函数可以访问本类的私有成员。

现在,我们学习一种新的情况——友元。

在C++中,这种关系以关键字friend声明。友元可以访问与其有好友关系的类中的私有成员。包括友元函数和友元类。

友元函数

如果在本类意外的其他地方定义了一个函数(这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数),在类体中用friend对该函数进行声明,此函数就称为本类的友元函数。一个类的友元函数可以访问这个类中的私有成员。


将普通函数声明为友元函数

========通过程序1.1来了解友元函数的性质和作用============

#include<iostream>
using namespace std;
class Time
{
	public:
		Time(int,int,int);//声明构造函数 
		friend void display(Time &);//声明display函数为Time类的友元
	private:
		int hour;
		int minute;
		int second; 
};
Time::Time(int h,int m,int s)//定义构造函数,完成初始化工作 
{
	hour=h;
	minute=m;
	second=s;
}
void display(Time &t)//友元函数,形参t是Time类对象的引用 
{
	cout<<t.hour<<"/"<<t.minute<<"/"<<t.second<<endl;
}
int main()
{
	Time t1(10,13,56);
	display(t1);
	return 0; 	
} 
 
  

运行结果:

分析:

display函数是一个在类外定义的非成员函数,它不属于任何一个类。如果在Time类的定义体中未声明display函数为friend函数,它是不能引用Time中的私有成员hour,minute和second的。

否则就会提示hour,minute和second是private函数,没有权限访问的错误。

由于我们在定义Time的时候,声明了display函数是其友元函数,Time所定义的所有的对象都会把dispaly函数作为自己的“朋友”,允许display函数引用其私有成员hour,minute和second.

但是要注意,我们在使用dispaly函数的时候,形参是对象的引用,实参是对象。

我们在友元函数中引用这些私有数据成员时,必须加上对象名,而不能写成:

	cout<<hour<<"/"<<minute<<"/"<<second<<endl;
因为display函数不是Time类的成员函数,不能默认引用Time类的数据成员,必须指定要访问的对象。

友元成员函数

friend函数不仅可以是一般函数(非成员函数),而且可以是另一个类中的成员函数。

在举这个例子之前,我们需要先了解“类的提前引用声明

在C++中允许对类做“提前引用”的声明,即在正式声明一个类之前,先声明一个类名,表示此类将在稍后声明。

函数的提前引用声明,只包含类名,不包含类体。

class Date;//对Date类做提前声明

类的提前声明的使用范围是有限的,在对一个类作了提前引用声明后,可以用该类的名字去定义指向该类型对象的指针变量或对象的引用。

这是因为指针变量和引用本身的大小是固定的,与它所指定的类对象的大小无关。

然后,只有在正式声明一个类之后才能用它去定义类对象。因为在正式声明类之前就去定义对象的话,编译系统并不知道对象的结构,也就没有办法给对象分配空间,所以不能定义对象。

================示例代码1.2==============================

#include<iostream>
using namespace std;
class Date;				//对Date类的提前引用声明
class Time 
{
	public:
		Time(int ,int ,int);
		void display(Date &);
	private:
		int hour;
		int minute;
		int second;
};
class Date
{
	public:
		Date(int,int,int);
		friend void Time::display(Date &);//声明Time类中的display函数为本类的友元函数
	private:
		int month;
		int day;
		int year; 
};
Time::Time(int h,int m,int s)		//定义类Time的构造函数
{
	hour=h;
	minute=m;
	second=s;
} 
/*
	display函数是Time类的成员函数;
	display函数是Date类的友元函数
*/ 
void Time::display(Date &d)			//display函数的作用是输出年月日和时分秒
{
	cout<<d.year<<"/"<<d.month<<"/"<<d.day<<endl;//引用Date类对象中的私有成员
	cout<<hour<<":"<<minute<<":"<<second<<endl; 
} 
Date::Date(int y,int m,int d)			//类Date的构造函数 
{
	year=y;
	month=m;
	day=d;	
}
int main()
{
	Time t1(15,30,30);
	Date d1(2013,9,8);
	t1.display(d1);
	return 0;
}

运行结果:

分析:

为了在Time类的定义中,能够定义形参是Date类对象引用的函数display。我们在代码的第三行,提前声明了类Date。

然后,在定义类Date的时候,我们在程序的第18行代码中,声明了Time的成员函数display函数为Date的友元成员函数,以达到能够访问Date中的私有数据成员的目的。

因为dispaly是Time中的成员函数,所以该函数可以访问Time类对象的私有数据成员;又因为Date类在声明的时候,将display函数声明为了其友成员函数,所以display函数也可以访问Date中的私有数据成员。

所以在程序的第倒数第3行才可以顺利的输出日期和时间。

友元类

不仅可以将一个函数声明为一个类的“朋友”,而且可以将一个类(例如类B)声明为另一个类(例如类A)的“朋友”。这是B类就是A类的友元类。友元类B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。

在A类的定义体中用一下语句声明B类为其友元类:

friend class B;

声明友元类的一般形式:

friend class B;

例如,我们可以将程序1.2中的Time类声明为Date类的友元类,这样Time中的所有函数都可以访问Date类中的数据成员。

修改代码如下

===============示例代码2.1============================

#include<iostream>
using namespace std;
class Date;				//对Date类的提前引用声明
class Time 
{
	public:
		Time(int ,int ,int);
		void display(Date &);
	private:
		int hour;
		int minute;
		int second;
};
class Date
{
	public:
		Date(int,int,int);
		friend class Time;//声明Time类为本类的友元类 
	private:
		int month;
		int day;
		int year; 
};
Time::Time(int h,int m,int s)		//定义类Time的构造函数
{
	hour=h;
	minute=m;
	second=s;
} 
/*
	display函数是Time类的成员函数;
	display函数是Date类的友元函数
*/ 
void Time::display(Date &d)			//display函数的作用是输出年月日和时分秒
{
	cout<<d.year<<"/"<<d.month<<"/"<<d.day<<endl;//引用Date类对象中的私有成员
	cout<<hour<<":"<<minute<<":"<<second<<endl; 
} 
Date::Date(int y,int m,int d)			//类Date的构造函数 
{
	year=y;
	month=m;
	day=d;	
}
int main()
{
	Time t1(15,30,30);
	Date d1(2013,9,8);
	t1.display(d1);
	return 0;
}

运行结果同示例代码1.2是一样的


说明:

关于友元有两点需要说明:

(1)友元的关系是单向的,而不是双向的。如果只声明了B类是A类的友元类,则B中的成员函数可以访问A中的私有数据成员;而A中的成员函数是不可以访问B中的数据成员的。

如果想要实现A和B互为友元类的话,需要即在A的声明体中声明B是其友元类,又要在B的声明体中声明A是其友元类。

(2)友元类的关系不能传递。如果B是A的友元类,C是B的友元类,不等于C是A的友元类。

在实际工作中,除非有必须,一般并不把整个类声明为友元类,而只是将确实有需要的成员函数声明为友元函数,这样更加安全一些。

文章评论

要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
鲜为人知的编程真相
鲜为人知的编程真相
 程序员的样子
程序员的样子
一个程序员的时间管理
一个程序员的时间管理
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
总结2014中国互联网十大段子
总结2014中国互联网十大段子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
代码女神横空出世
代码女神横空出世
为什么程序员都是夜猫子
为什么程序员都是夜猫子
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
旅行,写作,编程
旅行,写作,编程
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
那些争议最大的编程观点
那些争议最大的编程观点
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员都该阅读的书
程序员都该阅读的书
程序员的鄙视链
程序员的鄙视链
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员和编码员之间的区别
程序员和编码员之间的区别
如何成为一名黑客
如何成为一名黑客
我是如何打败拖延症的
我是如何打败拖延症的
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序员应该关注的一些事儿
程序员应该关注的一些事儿
我的丈夫是个程序员
我的丈夫是个程序员
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员必看的十大电影
程序员必看的十大电影
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
漫画:程序员的工作
漫画:程序员的工作
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
Java程序员必看电影
Java程序员必看电影
每天工作4小时的程序员
每天工作4小时的程序员
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有