友元函数、友元类、内部类详解!

1.友元函数

什么是友元函数?

类的友元函数可直接访问类中的私有成员变量,该函数是定义在类外的普通函数,不属于任何类,需要在类中加friend关键字声明。
比如我们在重载自定义类型输入输出操作符时就需要将操作符重载函数声明为友元函数:

class Date
{
     //此处就是友元函数的声明
	friend ostream& operator<<(ostream& out,const Date& d);
	friend istream& operator>>(istream& in, Date& d);

public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
	}
private:
	int _year;
	int _month;
	int _day;	
};
ostream& operator<<(ostream& out,const Date& d)
{
	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;
}

友元函数的作用?

为什么重载自定义类型输入输出操作符时,要在类外定义?
如果在类中定义输入输出操作符重载函数,那么隐含的this指针是第一个形参,使用该操作符时会出现如下问题:

int main()
{
	Date d1;
	d1<<cout;    //重载的 “<<” 只能这样使用
	return 0;
}

显然,上述写法不符合使用习惯,究其原因,是因为在类中定义的函数,第一个参数肯定是隐含的this指针,所以在使用重载的操作符时,操作符的位置要在对象后面,要解决这一问题,就要将cout、cin作为第一个参数。
因此,这两个运算符的重载函数要在类外定义。
此时又产生了一个问题,类外定义的函数并不能访问类对象的私有成员变量。所以这里需要把运算符重载函数声明为该类的友元函数

2.友元类

一个类需要访问另一个类的私有成员变量,就把该类声明为类一个类的友元类。

class Time
{ 
	friend class Date; //声明友元类
public:
	Time(int hour = 3, int minute = 10, int second = 45)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	Date(int year = 2021, int month = 6, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
		, _time()
	{
	}
	//要访问自定义类型Time中的私有成员变量,就要让Date类成为Time类的友元类
	void setTime(int hour,int minute,int second)
	{
		_time._hour = hour;
		_time._minute = minute;
		_time._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _time;
};
int main()
{
	Date d1;
	d1.setTime(11, 11, 11);
	return 0;
}

注:

  • 一个函数可以被声明为多个类的友元函数,一个类也可以被声明为多个类的友元类
  • 友元关系不能传递
  • 友元函数没有this指针!

友元的缺点:破坏了封装性!

3.内部类

类B定义在类A中,B天生就是A的友元类,B可以直接访问A的static、枚举成员,B访问A的普通私有成员变量需要A的对象。

class A
{
public:
	A(int a2 = 99)
		:_a2(a2)
	{}
	class B
	{
	public:
		void Print(const A& a)
		{
			cout << "a1 = " << _a1 << endl;     //直接访问外部类的私有成员变量
			cout << "a2 = " << a._a2 << endl;  //通过外部类对象访问外部类普通私有成员变量
		}
	private:
		int _b;
	};
private:
	static int _a1;
	int _a2;
};
int A::_a1 = 999;
int main()
{
	A::B bb;
	bb.Print(A());
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值