C++友元函数和友元类
通过 friend 关键字,我们可以将不属于当前类的一个函数在当前类中加以声明,该函数便可以成为当前类的友元函数。
【例 1】
也就是说,友元函数可以访问这个类中的私有成员。如果这个 display() 函数不是 book 类的友元函数,则在函数体中还必须调用 public 属性的成员函数。在此例中需要注意的是友元函数的形参是类对象的引用,同时在访问私有成员变量时必须要加上对象名。
除了顶层函数可以被定义为友元函数之外,其它类的成员函数同样可以声明为本类的友元函数,如例 2 所示。
【例 2】
为了能够共同显示年、月、日、时、分、秒信息,我们在 date 类中声明了一个 display() 函数,并且将该函数设置为 time 类的友元函数,如此一来,该函数既能访问 date 类中的私有成员变量,同时又能访问 time 类中的私有成员变量,打印时间自然不在话下。
这个例子有几点需要注意一下:
这三个需要注意顺序的地方需要大家特别关注一下,顺序一定不能搞错了,否则都是无法通过编译的。
无论是类的成员函数还是顶层函数,它们都是可以被多个类声明为友元函数的,如此一来就可以访问多个类中的私有成员变量,但是为了保证数据的安全,友元函数的使用宁缺毋滥。
除了可以利用 friend 关键字声明友元函数之外,我们还可以将其它类声明为当前类的友元类。友元类声明的语法非常简单,即为:
关于友元还有几点需要注意:
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
【例 1】
#include<iostream> using namespace std; class book { public: book(){} book(char* a, double p); friend void display(book &b); private: double price; char * title; }; book::book(char* a, double p) { title = a; price = p; } void display(book &b) { cout<<"The price of "<<b.title<<" is $"<<b.price<<endl; } int main() { book Alice("Alice in Wonderland",29.9); display(Alice); book Harry("Harry potter", 49.9); display(Harry); return 0; }在本例中,display() 是一个顶层函数,在 book 类中,我们借助 friend 关键字将其声明为友元函数。结果在 display() 函数体内,我们就能访问 private 属性的 title 和 price 成员变量。这就是友元函数的作用。
也就是说,友元函数可以访问这个类中的私有成员。如果这个 display() 函数不是 book 类的友元函数,则在函数体中还必须调用 public 属性的成员函数。在此例中需要注意的是友元函数的形参是类对象的引用,同时在访问私有成员变量时必须要加上对象名。
除了顶层函数可以被定义为友元函数之外,其它类的成员函数同样可以声明为本类的友元函数,如例 2 所示。
【例 2】
#include<iostream> using namespace std; class time; class date { public: date(int y,int m,int d); void display(time &t); private: int year; int month; int day; }; class time { public: time(int s,int m,int h); friend void date::display(time & t); private: int second; int minute; int hour; }; time::time(int s,int m,int h) { second = s; minute = m; hour = h; } date::date(int y,int m,int d) { year = y; month = m; day = d; } void date::display(time &t) { cout<<"The time is:"<<endl; cout<<year<<"/"<<month<<"/"<<day<<" "; cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl; } int main() { date d(2015,1,16); time t(20,2,30); d.display(t); return 0; }本例中定义了两个类 time 和 date,在 time 类中有 hour、minute 和 second 三个成员变量,分别代表时、分、秒。在 date 类中有 year、month 和 day 三个成员变量,分别代表年、月、日信息。
为了能够共同显示年、月、日、时、分、秒信息,我们在 date 类中声明了一个 display() 函数,并且将该函数设置为 time 类的友元函数,如此一来,该函数既能访问 date 类中的私有成员变量,同时又能访问 time 类中的私有成员变量,打印时间自然不在话下。
这个例子有几点需要注意一下:
- date 类的定义必须出现在 time 类之前,这么做是为了使得 display() 函数的函数声明能够在声明为友元函数之前;
-
display() 函数的形参为 time 类对象的引用,而 time 类又必须定义在 date 类之后,如此一来只能先将 time 类声明在 date 类之前了,如
class time;
这一语句即是为了声明time类; - display() 函数的定义需要放到 time 类定义的后面,这是因为 display() 函数中必须用到 time 类中的私有成员变量,因此在使用之前,这些成员变量必须先声明出来。
这三个需要注意顺序的地方需要大家特别关注一下,顺序一定不能搞错了,否则都是无法通过编译的。
无论是类的成员函数还是顶层函数,它们都是可以被多个类声明为友元函数的,如此一来就可以访问多个类中的私有成员变量,但是为了保证数据的安全,友元函数的使用宁缺毋滥。
除了可以利用 friend 关键字声明友元函数之外,我们还可以将其它类声明为当前类的友元类。友元类声明的语法非常简单,即为:
friend 类名;
【例 3】#include<iostream> using namespace std; class time; class date { public: date(int y,int m,int d); void display(time &t); private: int year; int month; int day; }; class time { public: friend date; time(int s,int m,int h); private: int second; int minute; int hour; }; time::time(int s,int m,int h) { second = s; minute = m; hour = h; } date::date(int y,int m,int d) { year = y; month = m; day = d; } void date::display(time &t) { cout<<"The time is:"<<endl; cout<<year<<"/"<<month<<"/"<<day<<" "; cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl; } int main() { date d(2015,1,16); time t(20,2,30); d.display(t); return 0; }在本例中,我们将 date 类声明为 time 类的友元类,则此时 date 类中的所有成员函数都将转化为 time 类的友元函数,可以访问 time 类中的所有成员。毫无疑问,date 类中 display() 函数同样也会成为 time 类的友元,因此利用 time 类对象 t 的引用便可以访问 time 类的私有成员变量了。此函数中类的声明及定义、函数的声明及定义位置同样需要注意。
关于友元还有几点需要注意:
- 例 3 中我们将 date 类声明为 time 类的友元类,此时 date 类中的所有函数都将成为 time 类的友元函数;
- date 类是 time 类的友元类,但是 time 类不是 date 类的友元类。友元关系是单向的,而不是双向的。如果需要将 time 类也声明名为 date 类的友元类,则需要另外在 date 类中声明;
- 友元关系不能传递,假设 A 类是 B 类的友元类,B 类是 C 类的友元类,这两点并不能得出 A 类是 C 类的友元类;
- 友元类会破坏数据的安全性,使用时宁缺毋滥。如果不是能够极大提高程序运行效率的情况,最好不要用友元。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。