友元函数与友元类

1.友元函数

友元函数的一些特点:
1.友元函数需要在类中任意位置进行声明,跟普通函数声明不同的是要加上friend 关键字,然后在类外进行实现,所以友元函数并不是类的成员函数。声明为友元函数之后,友元函数便可访问类中的私有成员。
2.友元函数没有隐藏的this指针,故参数列表中要多一个类的参数,相当于this指针,但是不一定为第一个参数,这使得友元函数的操作更加灵活,能够完成一些成员函数无法完成的操作,使用友元函数将会使类的操作更加灵活。
比如:

class Complex
{
public:
	Complex(int real = 0, int imag = 0) :m_real(real), m_imag(imag)
	{}
	~Complex()
	{}
	Complex operator+(int  a) {
		return Complex(m_real + a, m_imag);
	}
private:
	int m_real;
	int m_imag;
};

void main()
{
	Complex c, c1(1, 3);
	c = c1 + 10;
	//c = 10 + c1;  
}

这里我们通过运算符重载+号实现了Complex + int 即c = c1 + 10; ,编译器可以运行通过;
但是如果想实现int +Complex 即//c = 10 + c1; 的话,还是需要对+号进行运算符重载,重新解释+号的含义,但是由于类中的成员函数第一个参数默认为自身类型this,按照c = 10 + c1这样赋值运算的话,相当于调动10.operator(c1),10并不是一个对象,无法给Complex operator+(int a)函数中的this指针传参,无法编译通过。
那么如何解决上面的问题呢?这就需要用友元函数来实现了:


class Complex
{
	friend Complex operator+(int val, const Complex& c);  //将函数声明为友元函数,加friend关键字
	friend Complex operator+(const Complex& c1, const Complex& c2);
public:
	Complex(int real = 0, int imag = 0) :m_real(real), m_imag(imag)
	{}
	Complex& operator=(const Complex& c)
	{
		if (this != &c)
		{
			m_real = c.m_real;
			m_imag = c.m_imag;
		}
		return *this;
	}
	~Complex()
	{}
	Complex operator+(int  a) {
		return Complex(m_real + a, m_imag);
	}
private:
	int m_real;
	int m_imag;
};

Complex operator+(int val, const Complex& c)
{
	return Complex(val + c.m_real, c.m_imag);   //友元函数可以访问到类中的私有成员。
}

Complex operator+(const Complex& c1, const Complex& c2)
{
	return Complex(c1.m_real + c2.m_real, c1.m_imag + c2.m_imag);
}

void main()
{
	Complex c, c1(1, 3), c2(2, 5);
	c = c1 + 10;
	c = 10 + c1;
	c = c1 + c2;
}

友元函数与友元类_第1张图片
3.友元函数和static成员函数都没有this指针,static成员函数调动的优先级会比友元函数高。
4.友元函数不能用const修饰,友元函数的调用与普通函数的调用和原理相同。
5.一个函数可以是多个类的友元函数

class Stu;   //前向声明
class Test;

class Test
{
	friend void fun(const Test &t, const Stu &s);
public:
	Test()
	{
	}
private:
	int m_a = 0;  //默认值
	int m_b = 0;
};
class Stu
{
	friend void fun(const Test &t, const Stu &s);
public:
	int m_x = 0;
	int m_y = 0;;
};
 void fun(const Test &t, const Stu &s)  //fun()既是class Test也是class Stu的友元函数
{}
void main()
{
	Test t;
}

2.友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

特点:
1.友元关系是单向的,不具有交换性。
比如下面的例子有Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
2.友元关系不能传递
如果B是A的友元,C是B的友元,则不能说明C时A的友元。、


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

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
		,_t(9,30,45)
	{}
	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

void main()
{
	Time t1(11,2,3);
	Date d1(2020,3,15);
	Date d2 = d1;
	d1.SetTimeOfDate(1, 10, 11);
}


友元函数与友元类_第2张图片

你可能感兴趣的:(C++,c++)