友元
友元的引入
在C++中,私有成员对于外部的对象和方法来说是不可访问的,但是,在有时候需要在类的外部访问私有成员或保护成员,因此,就需要提供一种机制使得这一需求得以实现,而友元就为私有成员或保护成员打开了一扇通往类外部的大门。如果没有友元机制,外部函数访问类的私有数据必须通过调用公有的成员函数,这在需要平凡调用私有成员数据的情况下,会带来较大的开销,从而降低的程序运行效率。
友元函数
声明由友元函数时,只需要在其前面加上friend关键字。友元函数可以定义在类的外部也可以定义在类的外部。
将非成员函数声明为友元函数
在类的外部定义友元函数,在类内声明该函数为该类的友元函数。
class Person{ private: string name; int age; int *num; public: Person(string name,int age); Person(string name); Person(int age); Person(); Person(const Person &item); friend void disp(Person &person); }; void disp(Person &person){ cout<<person.name<<endl; return; } |
说明:
Ø 友元函数虽然可以访问私有成员,但是也得通过对象才能访问;
Ø 在定义友元函数时,由于友元函数不是成员函数,故定义的是普通的外部函数,也不能通过this指针访问对象的数据成员;
将成员函数声明为友元函数
一个类的成员函数也可以作为另一个类的友元函数,成为友元成员函数。
只是需要注意的是,在使用友元成员函数时,声明友元函数所在的类的位置。如果位置使用不当,就会导致访问失败,失败的本质原因是因为没有理解在使用类外定义或声明时,用于声明的那个类必须已经被定义过二不是声明过。一下通过两个例子来说明这一情况:
#include<iostream> #include<string> using namespace std; class Girl;
class Boy{
private: string name; public: Boy(string name){ this->name = name; } void disp(Girl &girl); };
class Girl{ private: string name; public: Girl(string name){ this->name = name; } friend void Boy::disp(Girl &girl); };
void Boy::disp(Girl &girl){ cout << "call the private member of Girl " << girl.name << endl; } int main(){ Boy boy(“Daniel”); Girl girl(“Danna”); boy.disp(); return 0; } |
结果就会显示:call the private member of Girl Danna |
而如果改变一下顺序,即:没有定义Boy但是声明了Boy
#include<iostream> #include<string> using namespace std; class Boy; class Girl{ private: string name; public: Girl(string name){ this->name = name; } friend void Boy::disp(Girl &girl); };
class Boy{
private: string name; public: Boy(string name){ this->name = name; } void disp(Girl &girl); };
void Boy::disp(Girl &girl){ cout << "call the private member of Girl " << girl.name << endl; } int main(){ Boy boy(“Daniel”); Girl girl(“Danna”); boy.disp(); return 0; } |
此时就会编译出错:error C2027: use of undefined type 'Boy' |
说明:
一个类的成员函数作为另一个类的友元函数时,就必须先定义这个类。并且在声明友元函数时需要加上成员函数所在类名。
友元类
类也可以作为作为另一个类的友元,称为友元类。
声明方法:
friend类名;
class A{…}; class B{… friend A;…}; |
说明:
当类A被说明为类B的友元类时,类A的所有成员函数都将成为类B的友元函数,即:类A中的所有成员函数都能通过B的对象访问B的所有数据成员,包括私有数据成员;