入门】23.C++中的友元"/>
【C++基础入门】23.C++中的友元
文章目录
一、友元的概念
二、友元的用法
三、友元的语法
四、友元的尴尬
五、注意事项
六、小结
一、友元的概念
- 什么是友元?
- 友元是 C++ 中的一种关系
- 友元关系发生在函数与类之间或者类与类之间
- 友元关系是单项的,不能传递
二、友元的用法
- 在类中以 friend 关键字声明友元
- 类的友元可以是其它类或者具体函数
- 友元不是类的一部分
- 友元不受类中访问级别的限制
- 友元可以直接访问具体类的所有成员
三、友元的语法
- 在类中用 friend 关键字对函数或类进行声明
先看一个不使用友元的代码:
#include <stdio.h>
#include <math.h>class Point
{double x;double y;
public:Point(double x, double y){this->x = x;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 = (p2.getY() - p1.getY()) * (p2.getY() - p1.getY()) +(p2.getX() - p1.getX()) * (p2.getX() - p1.getX());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;
}
输出结果如下:
这个程序在x 和 y中计算两点之间的距离时需要频繁访问私有成员 x 和 y,所以不得不调用 getX() 和 getY() 来访问 x 和 y,x 和 y 函数中调用了 8 次 getX() 和 getY(),很麻烦。
这个时候,就该我们的友元上场了:
#include <stdio.h>
#include <math.h>class Point
{double x;double y;
public:Point(double x, double y){this->x = x;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 = (p2.y - p1.y) * (p2.y - p1.y) +(p2.x - p1.x) * (p2.x - p1.x);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;
}
输出结果如下:
四、友元的尴尬
- 友元是为了兼顾 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 是 C 的友元,A 是 B 的友元,输出结果如下:
既然 A 可以访问 B,B 可以访问 C,那么 A 可以访问 C 么?把上面代码取消注释:
void getClassCName(ClassC& c){printf("c.n = %s\n", c.n);}
输出报错,这说明友元关系不具备传递性
六、小结
- 友元是为了兼顾 C 语言的高效而诞生的
- 友元直接破坏了面向对象的封装性
- 友元关系不具备传递性
- 类的友元可以是其它类的成员函数
- 类的友元可以是某个完整的类
更多推荐
【C++基础入门】23.C++中的友元
发布评论