C++ friend关键字详解

来源:互联网 发布:肾结石 知乎 编辑:程序博客网 时间:2024/06/16 17:25

一、为什么使用友元

       采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

 

二、友元函数和友元类

1、友元函数

(1)、普通函数做为类的一个友元函数

#include <iostream >   using  namespace  std; class  MyClass{public :       MyClass(string name)       {           m_name = name;    }    //声明一个友元函数    friend  void  Display(MyClass &mycalss);Protected:    string  m_name;};//定义这个友元函数//写成 void MyClass::Display(MyClass &mycalss)错误的写法 void  Display(MyClass &mycalss){     cout << "Access Protected data : "<< mycalss.m_name << endl; } //测试int main(int argc,char* argv[]){    MyClass test("Class A");        Display(test);    return 0;}


说明:

1. 声明这个友元函数可以在任何地方,可以在 public、protected 当然也可以在 privated 里,其作用是一样的。

2. 在这个友元函数里,你可以访问这个类里的所有的成员,所有的成员函数,而不管它是不是 public、protected 或 privated 的。

3. 定义友元函数时,不能写成 void MyClass::Display(MyClass &mycalss) 这点要注意。

      

(2)、一个普通函数可以是多个类的友元函数

#include <iostream >   using  namespace  std;class MyClass_B;class MyClass_A{public:       MyClass_A(string name)       {           m_name = name;    }    //声明一个友元函数    friend void Display(MyClass_A &myA, MyClass_B &myB);private:    string m_name;};class MyClass_B{public:       MyClass_B(string name)       {           m_name = name;    }       //注意,又声明一个友元函数    friend void Display(MyClass_A &myA, MyClass_B &myB);   private:    string m_name;};//定义这个友元函数void  Display(MyClass_A &myA, MyClass_B &myB){    cout << "MyClass A : "<< myA.m_name << endl;    cout << "MyClass B : "<< myB.m_name << endl;}//测试代码 www.2cto.comint main(int argc,char* argv[]){    MyClass_A testA("Class A");     MyClass_B testB("Class A");        Display(testA, testB);    return 0;}


 说明:函数声明可以有多个,但函数定义只能有一个

 

(3)、一个类的成员函数也可以是另一个类的友元

#include <iostream >   using  namespace  std; class MyClass_B;//A 类class MyClass_A{public:       MyClass_A(string name)       {           m_name = name;    }    void Function(MyClass_B &myB);private:    string m_name;};//B 类class MyClass_B{public:       MyClass_B(string name)    {        m_name = name;    }       //友元函数声明,注意和普通函数的区别    friend void MyClass_A::Function(MyClass_B &myB);   private:    string m_name;};//函数定义void MyClass_A::Function(MyClass_B &myB){    cout<<myB.m_name<<endl;}//测试代码int main(int argc,char* argv[]){    MyClass_A testA("Class A");     MyClass_B testB("Class B");        testA.Function(testB);    return 0;}


说明:通过将类A的Function函数声明为类B的友元函数,该函数就可以访问类B的所有数据成员,注意声明格式!

 

(4)、定义在类中的友元函数

#include<iostream>using std::cout;using std::endl;class X{public:X(int t=10):val(t){}friend void fun(const X &orj){cout<<orj.val<<endl;};//在类中进行定义的友元函数friend class Y;private:int val;};int main(){X x;fun(x);system("pause");return 0;}

来自MSDN的解释:

A friend function is a function that is not a member of a class but has access to the class's private and protected members. Friend functions are not considered class members; they are normal external functions that are given special access privileges. Friends are not in the class's scope, and they are not called using the member-selection operators (. and –>) unless they are members of another class. Afriend function is declared by the class that is granting access. Thefriend declaration can be placed anywhere in the class declaration. It is not affected by the access control keywords.

If you declare a friend function that was not previously declared, that function is exported to the enclosing nonclass scope.

Friend functions can be defined inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration).

Friend functions defined inside class declarations are not considered in the scope of the enclosing class; they are in file scope.

 

2、友元类

#include <iostream >   using  namespace  std; //类 Aclass MyClass_B;class MyClass_A{public:       MyClass_A(string name)       {           m_name = name;    }    //友元类声明    friend class MyClass_B;private:    string m_name;};//类 Bclass MyClass_B{public:       MyClass_B(string name)    {        m_name = name;    }       void Display(MyClass_A &myA);   private:    string m_name;};//成员函数void MyClass_B::Display(MyClass_A &myA){     cout<<myA.m_name<<endl; //访问A的私有成员    MyClass_A test("test");    cout<<test.m_name<<endl; //好像A的所有元素在B里都存在一样}//测试代码int main(int argc,char* argv[]){    MyClass_A testA("Class A");     MyClass_B testB("Class B");        testB.Display(testA);    return 0;}此时B可以访问A的所有元素,就好像A在B里面一样。

说明:

1、友类的每个成员函数都可以访问另一个类的所有成员。

2、友元关系不能被继承

3、友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B友元,要看在类中是否有相应的声明。 

4、友元关系不具有传递性。若类B是类A的友元,类C是类B的友元,类C不一定是类A的友元,同样要看类中是否有相应的声明。 

原创粉丝点击