前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

友元

作者头像
海盗船长
发布2020-08-27 17:23:11
6370
发布2020-08-27 17:23:11
举报
文章被收录于专栏:基础知识文章

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元函数

声明友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。 格式如下:

代码语言:javascript
复制
class Myclass
{
	public:
		……
		friend void add(int n );
	……
}

友元函数的特点:

友元函数可以使一个普通的函数,也可以是其他类的函数,但它一定不是本类的成员函数。 一般成员函数只可以访问一个类的私有和保护的成员,但友元函数可以访问多个类的私有和保护函数。 友元函数可以绕过成员函数,直接访问类的私有和保护函数,这样就避免了调用成员函数相关的开销。 如果没有友元功能,一个函数要想访问某个类的私有和保护的成员时,只能是将这个成员设置为公共的,这样一来用户就可以访问该类中的所有成员,从而破坏了信息的隐蔽性。 由于友元函数不是本类的成员函数。其定义和调用方式与普通函数一样,在调用友元函数时不需要使用“ · ”运算符,在定义时不需要实用类前缀。 友元函数并不是类的成员函数,他不带有this指针。所以必须用对象名或对象的引用作为友元函数的形参,并在函数体内使用运算符“.”来访问对象的成员。 由于友元函数可使用类里面的所有成员,从而破坏数据的安全性,所以使用友元函数必须谨慎,不要通过友元函数对数据成员进行危险的操作。

例:

代码语言:javascript
复制
//编写一个函数,以友元函数的方式计算一个点到一条直线的距离
#include<iostream>
#include<math.h>
using namespace std;
class Point
{
public:
	Point(int x1, int y1){ x = x1; y = y1; }
	int x, y;
};
class Line//线类
{
	int a, b, c;
public:
	Line(int a1, int b1, int c1){ a = a1; b = b1; c = c1; }
	friend double dist(Line l, Point p)
	{
		double d;
		d = abs(l.a*p.x + l.b*p.y + l.c) / (sqrt(l.a*l.a + l.b*l.b));
		return d;
	}
};
void main()
{
	Point p(10, 10);
	Line l(2, 4, -3);
	cout << "d=" << dist(l, p) << endl;
	system("pause");
}
在这里插入图片描述
在这里插入图片描述

友元类

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

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

例:编写一个程序,实现栈的压入和弹出。其中有两个类:一个是结点类Node,它包含结点值data和指向下一个节点next,另一个类是栈Stack,它包含头指针top。

代码语言:javascript
复制
#include<iostream>
using namespace std;
class Stack;
class Node
{
	int data;
	Node *next;
public:
	Node(int d)
	{
		data = d;
		next = NULL;
	}
	friend class Stack;
};

class Stack
{
	Node *top;
public:
	Stack()
	{
		top = NULL;
	}
	void push(int d)
	{
		Node *p = new Node(d);
		if (top != NULL)
			p->next = top;
			top = p;
	}
	int pop(int &c)
	{
		Node *p = top;
		if (top != NULL)
		{
			c = p->data;
			top = top->next;
			delete p;
			return 1;
		}
		else return 0;
	}
};

void main()
{
	Stack s;
	int c;
	s.push(1);
	s.push(2);
	s.push(3);
	s.push(4);
	cout << "出栈次序:";
	while (s.pop(c))
		cout << c << " ";
	cout << endl;
	system("pause");
}
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 友元函数
    • 声明友元函数
    • 友元类
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档