设为首页 加入收藏

TOP

C++学习笔记之友元(一)
2015-07-20 17:53:52 来源: 作者: 【 】 浏览:7
Tags:学习 笔记 之友
C++控制对类对象私有部分(private)的访问,通常只能通过公有的(public)类方法去访问。但是有时候这种限制太严格,不适合特定的问题,于是C++提供了另外一种形式的访问权限:友元。友元有三种:
?
友元函数
友元类
友元成员函数
二、友元函数
?
通过让函数称为友元函数,可以赋予该函数与类的成员函数相同的访问权限。为何需要友元呢?在为类重载二元运算符时常常需要友元,关于运算符的重载可以参考我的博文:
?
C++学习笔记之运算符重载
下面举例说明:
?
复制代码
?1 //mytime0
?2 #ifndef MYTIME0_H
?3 #define MYTIME0_H
?4?
?5 class Time
?6 {
?7 private:
?8 ? ? int hours;
?9 ? ? int minutes;
10 public:
11 ? ? Time();
12 ? ? Time(int h, int m = 0);
13 ? ? void addMin(int m);
14 ? ? void addHr(int h);
15 ? ? void reset(int h = 0, int m = 0);
16 ? ? Time operator*(double n) const;
17 ? ? void show() const;
18 };
19?
20 #endif
复制代码
?
?
复制代码
?1 #include
?2 #include "mytime0.h"
?3?
?4 Time::Time()
?5 {
?6 ? ? hours = minutes = 0;
?7 }
?8?
?9 Time::Time(int h, int m)
10 {
11 ? ? hours = h;
12 ? ? minutes = m;
13 }
14?
15 void Time::addMin(int m)
16 {
17 ? ? minutes += m;
18 ? ? hours += minutes / 60;
19 ? ? minutes %= 60;
20 }
21?
22 void Time::addHr(int h)
23 {
24 ? ? hours += h;
25 }
26?
27 void Time::reset(int h, int m)
28 {
29 ? ? hours = h;
30 ? ? minutes = m;
31 }
32?
33 Time Time::operator*(double mult)const
34 {
35 ? ? Time result;
36 ? ? long totalminutes = hours * mult * 60 + minutes * mult;
37 ? ? result.hours = totalminutes / 60;
38 ? ? result.minutes = totalminutes % 60;
39 ? ? return result;
40 }
41 void Time::show() const
42 {
43 ? ? std::cout << hours << " hours, " ? ?<< minutes << " minutes";
44 }
复制代码
?
?
上述代码建立了一个Time类并重载了这个类的*运算符,将一个Time值与一个double值结合在一起。但是,这将会产生一个问题,重载函数使得*运算符左侧的操作数是调用它的对象,即,下面的语句:
?
A = ?B * 1.75;(这里A,B均为Time类对象)
?
将被转化为:A = B.operator*(1.75);
?
但是,下面的语句会怎么转化呢?
?
A = 1.75 * B;
?
从概念上说,B * 1.75应该与1.75 * B相同,但是因为1.75不是Time类的对象,所以1.75无法调用被重载的*的成员函数operator*(),所以编译器这时候就不知道如何处理这个表达式,将会报错。
?
如果要求使用Time的*运算符时,只能按照B * 1.75这种格式书写,当然可以解决问题,但是显然不友好。
?
另一种解决方式--非成员函数。假如我们定义了一个非成员函数重载*:
?
Time operator*(double m, const Time & t);
?
?
则编译器既可以将 A = 1.75 * B与下面的非成员函数A = operator*(1.75, B);
?
但是如何实现这个函数呢?因为非成员函数不能直接访问类的私有数据,至少常规非成员函数不可以。但是,完事皆有例外,有一类特殊的非成员函数可以访问类的私有成员,即友元函数。
?
?
?
创建友元函数
?
将原型前面加上关键字friend,然后放在类声明中:
?
?
friend Time operator*(double n, const Time & t);?
该原型有如下两点特性:虽然operator*()函数是在类中声明的,但是它不是成员函数,因此不能用成员运算符来调用;虽然operator*()不是成员函数,但它与成员函数的访问权限相同。
?
编写函数定义
因为它不是成员函数,故不能用Time::限定符,特别注意,不要在定义中使用关键字friend,如下:
?
复制代码
1 Time operator*(double m, const Time & t) //不要使用friend关键字
2 {
3 ? ? Time result;
4 ? ? long totalminutes = t.hours * m * 60 + t.minutes * m;
5 ? ? result.hours = totalminutes / 60;
6 ? ? result.minutes = totalminutes % 60;
7 ? ? return result;
8 }
复制代码
?
?
然后,编译器就会调用刚才定义的非成员函数将A = 1.75 * B转换为A = operator*(1.75, B)。本人感觉就是重载了operator*()函数,当然是不是如此有待讨论。
?
总之,记住,类的友元函数是非成员函数,但其访问权限与成员函数相同。
?
三、友元类
?
一个类可以将其他类作为友元,这样,友元类的所有方法都可以访问原始类的私有成员(private)和保护成员(protected),也可以根据需要,只将特定的成员函数指定为另一个类的友元,哪些函数,成员函数或类为友元是由类自己定义的,不能外部强加,就好像你愿意把谁当做是你的朋友,是你自己在心里决定的,别人无法强制。
?
举例说明,假定需要编写一个模拟电视机和遥控器的简单程序。定义一个Tv类和一个Remote,分别表示电视机和遥控器,遥控器可以改变电视机的状态,应将Remote类作为Tv类的一个友元。
?
复制代码
?1 /*Tv and Remote classes*/
?2 #ifndef TV_H_
?3 #define TV_H_
?4 class Tv
?5 {
?6 public:
?7 ? ? friend class Remote; //声明谁是自己的“好基友”(友元)
?8 ? ?
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇hdu 4952 Number Transformation 下一篇UVA 10869 - Brownie Points II(..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: