类与对象(3)—— 友元函数和友元类

友元,是一种突破封装的方式,尽量少用

友元函数

需要友元解决的问题: 运用operator<<进行函数重载,需要输出,若把operator<<定义为成员变量函数,因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以我们要将operator<<重载成全局函数。但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。

把operator<<定义为另一个类的友元函数,则也可以访问类中的私有成员。

要点:
(1)定义友元函数:在类中定义函数的声明,并在前加friend
(2)友元函数主要解决访问类中的私有成员变量的问题
(3)函数可以被定义多个类的友元函数
如:friend ostream& operator<<(ostream& out, const Date& d, const Time& t);
同时定义为Date与Time类的友元函数
(4)友元函数不属于任何类,不是类的成员函数
(5)友元函数不能被const修饰
(6)友元函数可以在类定义的任何地方声明,不受类访问限定符限制

代码如下:

class Date
{
	//友元函数的声明
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
//把operator<<定为成员变量函数
	//d1<<cout;
	//void operator<<(ostream& out)   //void operator<<(Date* this,ostram& out)
	//{
	//	out << _year << "-" << _month << "_" << _day << endl;
	//}

	//void operator>>(istream& in)
	//{

	//}
	
	int GetYear()
	{
		return _year;
	} 
	
private:
	int _year;
	int _month;
	int _day;
};

//cout<<d1;
//设为全局性的函数,是为了解决参数抢占的问题
//若是成员函数,则为d1<<cout;
//变量是私有,则在Date类里面定义为友元函数,就可以访问私有成员变量
//出了作用域,out还在,所以要用引用
ostream& operator<<(ostream& out,const Date& d)   //void operator<<(Date* this,ostram& out)
{
	out <<d._year << "-" << d._month << "-" << d._day << endl;
	return out;//连续输出
}

istream& operator>>(istream& in, Date& d)
{
	in >> d._year >> d._month >> d._day;
	return in;
}
int main()
{
	Date d1,d2(2020,1,1);
	/*cin >> d1;
	cout << d2;*/
	/*d1 << cout;*/  //若定义在类中,这是输出的正确写法
	cin >> d1 >> d2;
	cout << d1 << d2;
	return 0;
}

友元类

友元类:实际上就是把这个类定义为另一个类的友元(即A类是B类的友元,A可以访问B中的私有成员变量以及保护成员变量)

要点
(1)友元关系不具有传递性
(2)友元关系不具备双向性(我是你的友元类,我可以访问你,但你不能访问我)
(3)若要相互访问对方类的成员,则要双方都要定义对方为自己的友元
(4)内部类就是外部类的友元类(内部类:如果一个类定义在另一个类的内部,这个内部类就叫做内部类)

代码如下:

class Time
{
	friend class Date;   //声明日期类为时间类的友元,则在日期类中就直接访问Time类中的私有变量 
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}

private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{  
	friend class Time;  //也可将Time定义为友元,Time则可以访问Date里面的私有成员
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	
	void SetTime0fDate(int hour, int minute, int second)
	{
		//直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}

private:
	int _year;
	int _month;
	int _day;
	Time _t;
};


int main()
{
	Date d1, d2(2020, 1, 1);
	/*cin >> d1; 
	cout << d2;*/
	/*d1 << cout;*/
	cin >> d1 >> d2;
	cout << d1 << d2;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值