1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 【C++深度剖析教程6】C++之友元

【C++深度剖析教程6】C++之友元

时间:2019-02-04 09:02:11

相关推荐

【C++深度剖析教程6】C++之友元

这几天在复习数学考试,都没有学C++,今天抽空来学一点。

什么是友元?

友元是C++中的一种关系友元发生在函数与类之间或者类与类之间友元关系是单向的,不能传递

在具体讲解友元的性质之前,我们先来看看一个程序,这个程序是计算两点之间的距离:

#include <stdio.h>#include <math.h>class Point{private:double x;double y;public:Point(double x,double y){this->x = x; //this指针指向当前的对象this->y = y;}double getX(){return x;}double getY(){return y;}};double func(Point& p1,Point& p2){double ret = 0;ret = (p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) +(p1.getY() - p2.getY()) * (p1.getY() - p2.getY());ret = sqrt(ret);return ret;}int main(){Point p1(1,2);Point p2(10,20);printf("p1(%f,%f)\n",p1.getX(),p1.getY());printf("p2(%f,%f)\n",p2.getX(),p2.getY());printf("|p1-p2| = %f\n",func(p1,p2));return 0;}

上面代码运行结果为:

p1(1.000000,2.000000)p2(10.000000,20.000000)|p1-p2| = 20.124612

看着也没什么大问题。下面我们来简单分析一下这个程序的实用性:进行计算这个两点之间的距离时的代码为:

ret = (p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) +(p1.getY() - p2.getY()) * (p1.getY() - p2.getY());

进行了8次函数的调用!!!这么简单的计算,就需要调用8次函数,这效率之慢在当初C++诞生的时候,是不被大多数人接受的,大多数人用C编程习惯了,都是可以直接这样调用的:

ret = (p1.x - p2.x) * (p1.x - p2.x) +(p1.y - p2.y) * (p1.y - p2.y);

然而C++里面你就不能像上面那样直接调用类(C里面可以是结构体或者数组)的成员变量。因为它是private类型的变量。那么在C++诞生的那个年代,人们为了让C++语言完全兼容C语言,就在C++中加入了友元的存在。那么友元的定义以及性质是什么样的呢?

在类中以friend关键字声明友元类的友元可以是其他类或者具体的函数友元不是类的一部分友元不受类中访问级别的限制友元可以直接访问具体类的所有成员

直接将上面的代码修改一下看看:

#include <stdio.h>#include <math.h>class Point{private:double x;double y;public:Point(double x,double y){this->x = x; //this指针指向当前的对象this->y = y;}double getX(){return x;}double getY(){return y;}friend double func(Point& p1,Point& p2);};double func(Point& p1,Point& p2){double ret = 0;ret = (p1.x - p2.x) * (p1.x - p2.x) +(p1.y - p2.y) * (p1.y - p2.y);ret = sqrt(ret);return ret;}int main(){Point p1(1,2);Point p2(10,20);printf("p1(%f,%f)\n",p1.getX(),p1.getY());printf("p2(%f,%f)\n",p2.getX(),p2.getY());printf("|p1-p2| = %f\n",func(p1,p2));return 0;}

运行结果为:

p1(1.000000,2.000000)p2(10.000000,20.000000)|p1-p2| = 20.124612

这样看来,我们已经实现了直接访问类的私有成员变量。上面的代码,func函数是Point类的友元,可以直接访问Point的所有数据。但是这样做,又不好,为什么呢?

友元的尴尬:

友元是为了兼顾C语言的高效性而诞生的友元直接破坏了面向对象的封装性友元在实际产品中的高效是得不偿失的友元在现代软件工程中已经被逐渐遗弃

虽然基于以上的尴尬让友元这个功能在现代软件工程中很少被使用,但是我们学习嘛,肯定是都要学的,哈哈~

友元需要注意的一些事项:

友元关系不具备传递性类的友元可以是其他类的成员函数类的友元可以是某个完整的类(所有的成员函数都是友元)

下面我们再分析一个代码,来看看友元的真实面目:

#include <stdio.h>class ClassC{const char* n;public:ClassC(const char* n){this->n = n;}friend class ClassB;};class ClassB{const char* n;public:ClassB(const char* n){this->n = n;}void getClassCName(ClassC& c){printf("c.n = %s\n", c.n);}friend class ClassA;};class ClassA{const char* n;public:ClassA(const char* n){this->n = n;}void getClassBName(ClassB& b){printf("b.n = %s\n", b.n);}/*void getClassCName(ClassC& c){printf("c.n = %s\n", c.n);}*/};int main(){ClassA A("A");ClassB B("B");ClassC C("C");A.getClassBName(B);B.getClassCName(C);return 0;}

运行结果为:

b.n = Bc.n = C

分析代码知:类B是C的友元,类A是B的友元,所以在B中可以直接访问C的私有成员变量,在A中可以直接访问B的成员变量。 那么在A中能否直接访问C呢?试验一下将上面的代码注释掉得部分恢复,编译运行,运行结果为:

test.cpp: In member function ‘void ClassA::getClassCName(ClassC&)’:test.cpp:6: error: ‘const char* ClassC::n’ is privatetest.cpp:44: error: within this context

很显然,A是不能访问C的私有成员的。

总结一下:

友元是为了兼顾C语言的高效而诞生的友元直接破坏了面向对象的封装性友元关系不具备传递性类的友元可以是其他类的成员函数类的友元可以是某个完整的类

想获得各种学习资源以及交流学习的加我(有我博客中写的代码的原稿):

qq:1126137994

微信:liu1126137994

可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。