友元

                                                                      友元

友元函数

1.友元函数的定义

2.全局函数作为友元函数

3.类成员函数作为友元函数

友元类

论友元

  1.友元函数的位置

  2.友元的利弊

 3.注意事项


       我们知道在C++中有三大特性,就是封装,继承,多态。对于一个类来说,我们实现了一个类的封装和隐藏。在我们平时的时候,都会将类的数据成员进行私有化,提供一个接口负责外界对私有的数据成员进行访问。但是,当我们定义了一些不属于类的成员函数,但是呢,这些函数却要频繁的被调用,来修改我们的成员变量,这时候我们就可以将这些函数定义为友元函数,以此来达到效果。

友元分为友元函数和友元类。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。

注意:友元一定是发生在不同类对象之间的。(对于运算符重载来说,MyString::MyString(const MyString & other) ,在同类中是可以直接访问对方的私有成员的

友元函数

1.友元函数的定义:

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它 不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字 friend。简单来说,你有一个好朋友,你的这个朋友可以看见你家的所有东西。

其格式如下: friend 类型 函数名(形式参数);

一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

2.全局函数作为友元函数:

class A{
public:
	A(int _x=1, int _y=1) :x(_x), y(_y){}
	void print()
	{
		cout << "x=" << x << endl;
		cout << "y=" << y << endl;
	}
	friend int product(A&a, A&b);
private:
	int x;
	int y;
};

int product(A&a, A&b)
{
	int tmp;
	tmp= a.x*b.x;
	tmp += a.y*b.y;
	return tmp;
}

int main()
{
	A a(2, 3);
	A b(6, 3);
	a.print();
	b.print();
	cout << product(a, b) << endl;
	return 0;
}

通过上面的代码,我们先定义了一个A类,这个类中定义了两个成员变量,分别是x和y。我们定义了一个全局函数,用来计算两个A类生成对象的乘积的值。这个时候,这个函数将会不断的频繁访问我们的类成员,因此,我们就将其声明为类A的友元函数,这个时候,就可以访问到类A的私有成员。

3.类成员函数作为友元函数

class A;

class B{
public:
	int product(A&a, A&b);
};

class A{
public:
	A(int _x=1, int _y=1) :x(_x), y(_y){}
	void print()
	{
		cout << "x=" << x << endl;
		cout << "y=" << y << endl;
	}
	friend int B::product(A&a, A&b);
private:
	int x;
	int y;
};
int B::product(A&a, A&b)
{
	int tmp;
	tmp = a.x*b.x;
	tmp += a.y*b.y;
	return tmp;
}

int main()
{
	A a(2, 3);
	A b(6, 3);
	a.print();
	b.print();
	B tmp;
	cout << tmp.product(a, b) << endl;
	return 0;
}

对于上面功能,这个时候,我们使用了类的对象函数,作为了类的友元函数,也可以实现这个功能。 但是在这个之前,我们要补充一个知识,就是前向声明。

前向声明,是一种不完全型(forward declaration)声明,即只需提供类名(无需提供 类实现)即可。正因为是(incomplete type)功能也很有限:

(1)不能定义类的对象。

(2)可以用于定义指向这个类型的指针或引用。

(3)用于声明(不是定义),使用该类型作为形参类型或者函数的返回值类型。

在上诉的代码中,我们可以看见,我们首先前向声明了一个类A,因为在B类中,成员方法的参数中使用了这个类的引用。但是在类B中,我们不能将这个成员方法实现。因为呢,虽然我们在前面声明了一个类A,但是我们并没有实现,因此,我们并不能知道A类中具体的实现,因此,我们需要将我们的类B中 A的友元函数在类A实现之后,在进行实现。

友元类

    友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包 括私有成员和保护成员)。

    当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义 友元类的语句格式如下:

    friend class 类名;

    其中:friend 和 class 是关键字,类名必须是程序中的一个已定义过的类。

   例如,以下语句说明类 B 是类 A 的友元类:

   class A

   { …

   public: friend class B;

   … };

经过以上说明后,类 B 的所有成员函数都是类 A 的友元函数,能存取类 A 的私有成员和 保护成员。

class A{
public:
	A(int _x=1, int _y=1) :x(_x), y(_y){}

	friend class B;
private:
	int x;
	int y;
};

class B{
public:
	A a;
	void print()
	{
		cout << "x=" << a.x << endl;
		cout << "y=" << a.y << endl;
	}
	int product(A&a, A&b)
	{
		int tmp;
		tmp = a.x*b.x;
		tmp += a.y*b.y;
		return tmp;
	}
};


int main()
{
	A a(2, 3);
	A b(6, 3);
	B tmp;
	cout << tmp.product(a, b) << endl;
	tmp.print();
	return 0;
}

在上面的代码中,我们将类B设置为类A的友元函数,对于B类中成员方法都可以访问类A中的成员变量。

论友元

  1.友元函数的位置:

     友元声明以关键字 friend 开始,它只能出现在类定义中。因为友元不是授权类的成员, 所以它不受其所在类的声明区域 public private 和 protected 的影响。通常我们选择把所有友元 声明组织在一起并放在类头之后。

2.友元的利弊

    友元不是类成员但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率, 但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过,类的访 问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特别语法现象。

3.注意事项

(1) 友元关系不能被继承。

(2) 友元关系是单向的,不具有交换性。若类 B 是类 A 的友元,类 A 不一定是类 B的 友元,要看在类中是否有相应的声明。

(3) 友元关系不具有传递性。若类 B 是类 A 的友元,类 C 是 B 的友元,类 C 不一定是 类 A 的友元,同样要看类中是否有相应的申明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值