根据36 类和对象-友元-全局函数做友元_哔哩哔哩_bilibili复现出如下代码:
- #include
- using namespace std;
- class Building
- {
- private:
- int ws;//卧室
- public:
- int kt;//客厅
- Building();
- };
- Building::Building()//构造函数赋初值
- {
- int ws = 1;
- int kt = 2;
- }
- int visit(Building b)
- {
-
- cout << "客厅=" << b.kt << endl;
- return 0;
- }
- int main()
- {
- Building b1;
- visit(b1);
- }
在这里,实际上,我们也可以把构造函数写在类里面,实现同样的效果:
- class Building
- {
- private:
- int ws;//卧室
- public:
- int kt;//客厅
- Building()//构造函数赋初值
- {
- int ws = 1;
- int kt = 2;
- }
- };
结果:
为什么我写了半天,最后返回的是一个随机值呢?
根本原因,就在于构造函数的格式不对,构造函数在赋初值时,类里面的变量(成员)前不应该(不能)有类型说明
(C语言日记 33 构造函数_宇 -Yu的博客-CSDN博客中,就有构造函数定义和声明的使用格式)
如果没有类型说明,那么构造函数相当于还在给类的(公有,私有)成员变量赋初值,
而加上了类型说明,那么相当于构造函数在给函数内自定义的变量赋初值,和类里面的成员没有关系,而类的成员实际上并没有被赋值,输出时返回的自然就是一个随机值;所以,我们应将程序改为:(通过实参形参调用传值)
- #include
- using namespace std;
- class Building
- {
- private:
- int ws;//卧室
- public:
- int kt;//客厅
- Building();
- };
- Building::Building()//构造函数赋初值
- {
- ws = 1;
- kt = 2;
- }
- int visit(Building b)
- {
-
- cout << "客厅=" << b.kt << endl;
- return 0;
- }
- int main()
- {
- Building b1;
- visit(b1);
- }
结果:
修改为36 类和对象-友元-全局函数做友元_哔哩哔哩_bilibili源程序所设计的各个模块的样子:
- #include
- using namespace std;
- class Building
- {
- private:
- int ws;//卧室
- public:
- int kt;//客厅
- Building()//构造函数赋初值
- {
- ws = 1;
- kt = 2;
- }
- };
- //
- int visit(Building b)
- {
- cout << "客厅=" << b.kt << endl;
- return 0;
- }
- void test()
- {
- Building b1;
- visit(b1);
- }
- int main()
- {
- test();
- }
我们可以通过实参形参调用传值,也可以用指针,引用的方式传值:
- int visit(Building* b)
- {
- cout << "客厅=" << b->kt << endl;
- return 0;
- }
- void test()
- {
- Building b1;
- visit(&b1);
- }
注解:
(1):这里的“->”,表示:通过指针来访问结构体变量(的具体内容)C语言日记 28 结构体类型_宇 -Yu的博客-CSDN博客
(2):
visit(&b1);
中,&表示取(地)址,不能改为*(如果改为*,则表示访问该指针指向的目标对象的具体内容)
如果一定不想这样写的话,可以改写为:
- void test()
- {
- Building b;
- Building *b1=&b;
- visit(b1);
- }
- int visit(Building &b)
- {
- cout << "客厅=" <
- return 0;
- }
- void test()
- {
- Building b;
- visit(b);
- }
注解:
(1):引用访问,就和对象访问自身的内容属性引用,不能用“->”;(“->”只能用于指针)
(2):
visit(b);
只能这么写,不能在前面加“*”(加了表求指向目标的值),也不能加“&”(加了表求指向目标的地址)
二、访问内部私有成员(这就要用到友元了)
这时,既然我们想要让全局函数访问内部私有成员,只要在前面的基础上
在visit()函数中写一个输出私有函数的语句:
cout << "卧室=" << b.ws << endl;
并且在类的成员声明里面加(上)一个友元函数的声明:
friend void visit(Building b);
值得注意的是:
这里的友元函数的声明加在类(体)的任意处都可以:
友元函数不是成员函数,无论是放在private私有成员说明中:
- #include
- using namespace std;
- class Building
- {
- private:
- int ws;//卧室
- friend void visit(Building b);
- public:
- int kt;//客厅
- Building()//构造函数赋初值
- {
- ws = 1;
- kt = 2;
- }
- };
- //
- void visit(Building b)
- {
- cout << "客厅=" << b.kt << endl;
- cout << "卧室=" << b.ws << endl;
- }
- void test()
- {
- Building b1;
- visit(b1);
- }
- int main()
- {
- test();
- }
还是放在成员说明之外:
- #include
- using namespace std;
- class Building
- {
- friend void visit(Building b);
- private:
- int ws;//卧室
- public:
- int kt;//客厅
- Building()//构造函数赋初值
- {
- ws = 1;
- kt = 2;
- }
- };
- //
- void visit(Building b)
- {
- cout << "客厅=" << b.kt << endl;
- cout << "卧室=" << b.ws << endl;
- }
- void test()
- {
- Building b1;
- visit(b1);
- }
- int main()
- {
- test();
- }
最终结果都可以访问类的内部私有成员:
例8-14 使用普通函数计算两点间的距离。
源程序:
- #include
- #include
- using namespace std;
- class Point //Point 类定义
- {
- private://私有数据成员
- int x, y;
- public://外部接口
- Point(int x = 0, int y = 0) :x(x), y(y) { }
- int getX() { return x; }
- int getY() { return y; }
- friend float dist(Point& a, Point& b); //友元函数是一个普通函数
- };
- float dist(Point& a, Point& b)//普通函数的定义
- {
- double x = a.x - b.x;
- double y = a.y - b.y;
- return(float)sqrt(x * x + y * y);
- }
- //
- int main()
- {
- Point p1(3, 5), p2(11, 6);
- cout << "The distance is:";
- cout << dist(p1, p2) << endl;
- //调用普通友元函数
- return 0;
- }
-
结果:
The distance is:8.06226
(1):#include :相当于#include (C语言),当然这里不写也无所谓,如同:C语言日记 8 C++语句_宇 -Yu的博客-CSDN博客:#include <math.h>//可有可无
(2):其中的: friend float dist(Point &a, Point &b); 只是一个用引用作为函数参数的形式,可以改(写)为:(实参形参传递数据)
friend float dist(Point a, Point b);
详见书P105(当然,像这样用实参形参传递数据,采用的是值传递的传值的方式);
也可以改(写)为:(指针传递数据)
- #include
- #include
- using namespace std;
- class Point //Point 类定义
- {
- private://私有数据成员
- int x, y;
- public://外部接口
- Point(int x = 0, int y = 0) :x(x), y(y) { }
- int getX() { return x; }
- int getY() { return y; }
- friend float dist(Point* a, Point* b); //友元函数是一个普通函数
- };
- float dist(Point* a, Point* b)//普通函数的定义
- {
- double x = a->x - b->x;
- double y = a->y - b->y;
- return(float)sqrt(x * x + y * y);
- }
- //
- int main()
- {
- Point p1(3, 5), p2(11, 6);
- cout << "The distance is:";
- cout << dist(&p1, &p2) << endl;
- //调用普通友元函数
- return 0;
- }
当然,改写为指针传递数据的方式的修改过程,比起其他两种情况要更为复杂一些:
改动处:
(1):形参a和b改为指针
(2):“->”改为"."
(3):调用dist函数时,里面的实参p1,p2改为取(地)址“&p1,&p2”
(3):另外,(如果)我们想要在类中(里面)定义该友元函数(不用分开声明,直接一次性定义完成就行了)最终结果也一样:
- #include
- using namespace std;
- class Point //Point 类定义
- {
- private://私有数据成员
- int x, y;
- public://外部接口
- Point(int x = 0, int y = 0) :x(x), y(y) { }
- int getX() { return x; }
- int getY() { return y; }
- friend float dist(Point a, Point b)//友元函数是一个普通函数
- {
- double x = a.x - b.x;
- double y = a.y - b.y;
- return(float)sqrt(x * x + y * y);
- }
- };
- //
- int main()
- {
- Point p1(3, 5), p2(11, 6);
- cout << "The distance is:";
- cout << dist(p1, p2) << endl;
- //调用普通友元函数
- return 0;
- }
而在这里我们可以看到,实际上想要访问本类的内部私有成员,根本还用不着什么友元函数,
直接设立一个公有的类函数直接访问调用私有成员就可以:
- #include
- #include
- using namespace std;
- class Point //Point 类定义
- {
- private://私有数据成员
- int x, y;
- public://外部接口
- Point(int x = 0, int y = 0) :x(x), y(y) { }
- int getX() { return x; }
- int getY() { return y; }
- float dist(Point* a, Point* b)//普通函数的定义
- {
- double x = a->x - b->x;
- double y = a->y - b->y;
- return(float)sqrt(x * x + y * y);
- }
- };
- //
- int main()
- {
- Point p1(3, 5), p2(11, 6);
- cout << "The distance is:";
- cout << dist(&p1, &p2) << endl;
- //调用普通友元函数
- return 0;
- }
结果:
为什么???
调用类中定义的函数必须用对象(才能调用):(这里用p1,p2都可以)
- #include
- #include
- using namespace std;
- class Point //Point 类定义
- {
- private://私有数据成员
- int x, y;
- public://外部接口
- Point(int x = 0, int y = 0) :x(x), y(y) { }
- int getX() { return x; }
- int getY() { return y; }
- float dist(Point* a, Point* b)//普通函数的定义
- {
- double x = a->x - b->x;
- double y = a->y - b->y;
- return(float)sqrt(x * x + y * y);
- }
- };
- //
- int main()
- {
- Point p1(3, 5), p2(11, 6);
- cout << "The distance is:";
- cout << p1.dist(&p1, &p2) << endl;
- //调用普通友元函数
- return 0;
- }
(2):成员函数做友元
例8-15 使用其他类的成员函数实现两点间距离的计算。
源程序:
- #include
- using namespace std;
- class Point;//声明 Point 类
- class Dist//Dist 类定义
- {
- public:
- float dist(Point& a, Point& b);
- };
- class Point//Point 类定义
- {
- private://私有数据成员
- int x, y;
- public://外部接口
- Point(int x = 0, int y = 0) :x(x), y(y) {}
- int getx() { return x; }
- int getY() { return y; }
- friend float Dist::dist(Point& a, Point& b);
- //友元函数是Dist的成员函数
- };
- float Dist::dist(Point& a, Point& b) //友元函数的定义
- {
- double x = a.x - b.x;
- double y = a.y - b.y;
- return (float)sqrt(x * x + y * y);
- }
- int main()
- {
- Point p3(10, 8), p4(4, 12);
- Dist d;
- cout << "The distance is:"; cout << d.dist(p3, p4) << endl;
- //调用成员友元函数
- return 0;
- }
The distance is:7.2111
(3):友元类
见下一篇日记
(其实是下一篇日记太短,而这篇日记太长,把这个内容换一个位置,调整一下两篇的篇幅)