zoukankan      html  css  js  c++  java
  • 详解C++ friend关键字

    1. 为什么要使用友元?

      通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为 public( 共用的) ,然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它;另一种方法是利用 C++ 的 friend 修饰符,可以让一些你设定的函数能够对这些私有或保护数据进行操作。

    2. 使用友元有哪些缺点?

      使用友元的同时也破坏了类的封装特性,这即是友元最大的缺点。当对外声明为友元后,你的所有细节全部都暴露给了对方。

    就好像你告诉你朋友你很有钱这个密秘,进而又把你有多少钱,多少古董,多少家产,多少小妾等等所有的家底全给他说了。 

    3. 友元怎样理解?

      定一个友元函数,或是友元类,就是告诉对方:我的所有元素对你是开放的。这种 friend 是建立在灰常灰常灰常信任对方的基础上的。

    4.普通函数做为类的一个友元函数

      在类里声明一个普通函数,在前面加上 friend 修饰,那么这个函数就成了该类的友元。这时这个普通函数可以访问该类的一切成员

    #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) 这点要注意。因为友元函数不是成员函数

    5. 一个普通函数可以是多个类的友元函数

      在每个类里面都有一个友元函数的声明,声明可以有多个,但定义只能有一个

    #include <string>
    #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;
    }
    
    //测试代码
    int main(int argc,char* argv[])
    {
        MyClass_A testA("Class A");  
        MyClass_B testB("Class A");  
        
        Display(testA, testB);
        system("pause");
        return 0;
    }

    6.一个类的成员函数也可以是另一个类的友元

    //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);
        system("pause");
        return 0;
    }

    7. 整个类也可以是另一个类的友元

    //类 A
    class MyClass_B;
    
    class MyClass_A
    {
    public:    
        MyClass_A(string name)    
        {    
            m_name = name;
        }
    
        //友元类声明
        friend class MyClass_B;
    
    private:
        string m_name;
    };
    
    //类 B
    class 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;
    }
  • 相关阅读:
    Scala编程基础
    大数据学习环境搭建(CentOS6.9+Hadoop2.7.3+Hive1.2.1+Hbase1.3.1+Spark2.1.1)
    hadoop2.7.3编译,支持snappy、bzip2本地压缩
    ABAP非Unicode系统中字符串拼接(CONCATENATE)时吃字符问题
    Hadoop学习笔记
    HIVE开发总结
    中文字符截取乱码问题
    替换空字符NULL(字符编码为0的字符)
    Generate Time Data(普通日期主数据)
    Generate Time Data(财务日期主数据)
  • 原文地址:https://www.cnblogs.com/wiessharling/p/3313196.html