C++——友元(この一編を見れば十分!)

43857 ワード

文書ディレクトリ
  • 1グローバル関数は友元
  • をします
  • 2類友元
  • 3メンバー関数を友元
  • とする

    生活の中であなたの家はリビング(public)があって、あなたの寝室(private)のリビングがあってすべての来た客はすべて入ることができて、しかしあなたの寝室は私有で、つまりあなただけが入ることができます
    しかし、隣の王さんも入ることができます.
    プログラムでは,一部のプライベート属性もクラス外の特殊な関数やクラスにアクセスさせたいと考え,友元の技術を用いる必要がある.
    友元の目的は、1つの関数またはクラスを別のクラスのプライベートメンバーにアクセスさせることです.
    友元のキーワードはfriend
    友元の3つの実現
  • グローバル関数は友元
  • をします
  • 類友元
  • メンバー関数を友元
  • とする
    1グローバル関数を友元にする
    まず、公共メンバー変数がリビング、プライベートメンバー変数が寝室の家屋クラスを定義します.
    class Building
    {
         
    	// Building     ,        
    	Building()
    	{
         
    		m_SittingRoom = "  ";
    		m_BedRoom = "  ";
    	}
    	
    	string m_SittingRoom;	//   
    
    private:
    
    	string m_BedRoom;		//   
    };
    

    次に、Buildingクラスのプライベートメンバーにアクセスするグローバル関数laoWang()を定義します.
    void laoWang1(Building *building)
    {
         
    	cout << "              :(    ) " << building->m_SittingRoom << endl;
    
    	cout << "              :(    ) " << building->m_BedRoom << endl;
    }
    

    もちろん、参照伝達や最も簡単な値で伝達することもできます.
    void laoWang2(Building &building)
    {
         
    	cout << "              :(    ) " << building.m_SittingRoom << endl;
    
    	cout << "              :(    ) " << building.m_BedRoom << endl;
    }
    
    void laoWang3(Building building)
    {
         
    	cout << "              :(     ) " << building.m_SittingRoom << endl;
    
    	cout << "              :(     ) " << building.m_BedRoom << endl;
    }
    

    最後にテスト関数test()を定義し、laoWang()というグローバル関数を友元アクセスクラスのプライベートメンバーとして実現します.
    void test()
    {
         
    	Building building;
    	laoWang1(&building);
    	laoWang2(building);
    	laoWang3(building);
    }
    

    しかし、グローバル関数アクセスクラスのプライベートメンバーはまだ実現できません.
    キーコード
    friend void laoWang1(Building *building);
    friend void laoWang2(Building &building);
    friend void laoWang3(Building building);
    

    Buildingクラスで友元関数を宣言し、コンパイラlaoWangグローバル関数がBuildingクラスの親友であることを伝えます.Buildingオブジェクトのプライベートメンバーにアクセスできます.
    class Building
    {
         
    	//       laoWang      Building       ,    Building       
    	friend void laoWang1(Building *building);
    	friend void laoWang2(Building &building);
    	friend void laoWang3(Building building);
    
    public:
    
    	Building()
    	{
         
    		m_SittingRoom = "  ";
    		m_BedRoom = "  ";
    	}
    	
    	string m_SittingRoom;	//   
    
    private:
    
    	string m_BedRoom;		//   
    };
    

    次に、友元アクセスクラスとしてグローバル関数を使用するプライベートメンバーの完全なサンプルコードを示します.
    #include 
    #include 
    
    using namespace std;
    
    //    
    class Building
    {
         
    	//       laoWang      Building       ,    Building       
    	friend void laoWang1(Building *building);
    	friend void laoWang2(Building &building);
    	friend void laoWang3(Building building);
    
    public:
    
    	Building()
    	{
         
    		m_SittingRoom = "  ";
    		m_BedRoom = "  ";
    	}
    	
    	string m_SittingRoom;	//   
    
    private:
    
    	string m_BedRoom;		//   
    };
    
    
    
    //    
    void laoWang1(Building *building)
    {
         
    	cout << "              :(    ) " << building->m_SittingRoom << endl;
    
    	cout << "              :(    ) " << building->m_BedRoom << endl;
    }
    
    void laoWang2(Building &building)
    {
         
    	cout << "              :(    ) " << building.m_SittingRoom << endl;
    
    	cout << "              :(    ) " << building.m_BedRoom << endl;
    }
    
    void laoWang3(Building building)
    {
         
    	cout << "              :(     ) " << building.m_SittingRoom << endl;
    
    	cout << "              :(     ) " << building.m_BedRoom << endl;
    }
    
    void test()
    {
         
    	Building building;
    	laoWang1(&building);
    	laoWang2(building);
    	laoWang3(building);
    }
    
    
    int main()
    {
         
    	test();
    }
    

    出力結果
                  :(    )   
                  :(    )   
                  :(    )   
                  :(    )   
                  :(     )   
                  :(     )   
    

    2類は友元を作る
    まず、アクセスするプライベート変数が属するBuildingクラスを宣言し、次の良いLaoWangクラスでコンパイラがBuildingクラスを認識しないことを防止します(もちろん、Buildingクラスを定義してから、隣の王LaoWangクラスを定義することもできます.Buildingクラスを宣言する必要はありません).
    class Building;
    

    次に、隣の王LaoWangクラスを定義し、Buildingタイプのポインタ変数buildingを宣言します.ここで、メンバー関数は、クラス内宣言、クラス外定義を使用して、クラスの内容を簡略化できます(グローバル関数を友元とする例では、クラス内でメンバー関数を宣言して定義する方法を使用します.両方の方法があります).
    class LaoWang
    {
         
    public:
    	//LaoWang     
    	LaoWang();
    
    	void visit();	//        Building    
    
    	Building * building;
    
    
    private:
    
    
    };
    

    次にBuildingクラスの定義を示します
    class Building
    {
         
    public:
    	//Building         ,     
    	Building();
    		
    	string m_SittingRoom;	//   
    	
    private:
    	
    	string m_BedRoom;		//   
    
    };
    

    次に、クラス外定義メンバー関数を示します.クラス外定義では、コンパイラにどのクラスに属するかを示すために、メンバー関数にクラスの役割ドメイン(クラス名::メンバー関数名())を追加する必要があります.
    //Building      
    Building::Building()
    {
         
    	m_SittingRoom = "  ";
    	m_BedRoom = "  ";
    
    	cout << m_SittingRoom << endl;
    	cout << m_BedRoom << endl;
    
    }
    
    //LaoWang     
    LaoWang::LaoWang()
    {
         
    	//        
    	building = new Building;	//         ,   building  
    
    }
    
    //LaoWang     visit()
    void LaoWang::visit()
    {
         
    	cout << "         :" << building->m_SittingRoom << endl;
    
    	cout << "         :" << building->m_BedRoom << endl;
    }
    

    最後にテスト関数を定義し、クラスが他のクラスのプライベートメンバーに友元としてアクセスできるようにします.
    void test()
    {
         
    	LaoWang lw	//    LaoWang    ;
    	lw.visit();
    }
    

    しかし、1つのクラスが別のクラスにアクセスするプライベートメンバーはまだ実現できません.
    キーコード
    friend class LaoWang;
    

    Buildingクラスに友元クラスを宣言し、コンパイラLaoWangクラスがBuildingクラスの親友であることを伝え、Buildingオブジェクトのプライベートメンバーにアクセスできます.
    class Building
    {
         
    	//      ,LaoWang  Building     ,    Building      
    	friend class LaoWang;
    public:
    	
    	Building();
    		
    	string m_SittingRoom;	//   
    	
    private:
    	
    	string m_BedRoom;		//   
    
    };
    

    次に、クラスが友元として実装されたクラスが別のクラスのプライベートメンバーにアクセスする完全なサンプルコードを示します.
    #include 
    #include 
    
    using namespace std;
    
    //     
    
    class Building;
    class LaoWang
    {
         
    public:
    
    	LaoWang();
    
    	void visit();	//        Building    
    
    	Building * building;
    
    
    private:
    
    
    };
    
    //    
    class Building
    {
         
    	//      ,LaoWang  Building     ,    Building      
    	friend class LaoWang;
    public:
    	
    	Building();
    		
    	string m_SittingRoom;	//   
    	
    private:
    	
    	string m_BedRoom;		//   
    };
    
    //         
    
    Building::Building()
    {
         
    	m_SittingRoom = "  ";
    	m_BedRoom = "  ";
    }
    
    LaoWang::LaoWang()
    {
         
    	//        
    	building = new Building;
    }
    
    void LaoWang::visit()
    {
         
    	cout << "    LaoWang     :" << building->m_SittingRoom << endl;
    
    	cout << "    LaoWang     :" << building->m_BedRoom << endl;
    }
    
    void test()
    {
         
    	LaoWang lw;
    	lw.visit();
    }
    
    int main()
    {
         
    	test();
    
    	return 0;
    }
    

    出力結果
        LaoWang     :  
        LaoWang     :  
    

    3メンバー関数を友元にする
    クラス作友元と同様に、私たちはまずBuildingクラスを宣言し、次の良いLaoWangクラスでコンパイラがBuildingを知らないことを防止します.
    class Building;
    

    次にLaoWangクラスを定義し、同様にメンバー関数を使用してクラス内で宣言し、クラス外で定義する方法を採用します.2つのアクセス関数を定義します
  • visit 1()は、Buildingのプライベートメンバー
  • にアクセスできます.
  • visit 2()は、Buildingのプライベートメンバー
  • にアクセスできません.
    class LaoWang
    {
         
    public:
    
    	LaoWang();
    	void visit1();	// visit1()          Building      
    	void visit2();	// visit2()         Building      
    
    	Building *building;
    
    private:
    
    };
    

    Buildingクラスの定義を次に示します
    class Building
    {
         
    public:
    	Building();
    
    	string m_SittingRoom;	//  
    	
    private:
    
    	string m_BedRoom;		//  
    };
    

    次に、クラス外定義メンバー関数を示します.
    //LaoWang      
    LaoWang::LaoWang()
    {
         
    	building = new Building;
    }
    
    //LaoWang      visit1()
    void LaoWang::visit1()
    {
         
    	cout << "    LaoWang   visit1()      :" << building->m_SittingRoom << endl;
    	cout << "    LaoWang   visit1()      :" << building->m_BedRoom << endl;	
    }
    
    //LaoWang      visit2()
    void LaoWang::visit2()
    {
         
    	cout << "    LaoWang   visit2()      :" << building->m_SittingRoom << endl;
    	//cout << "    LaoWang   visit2()      :" << building->m_BedRoom << endl;	//  !        
    }
    
    //Building      
    Building::Building()
    {
         
    	m_SittingRoom = "  ";
    	m_BedRoom = "  ";
    }
    

    最後に、1つのテスト関数でメンバー関数を友元として実装し、別のクラスのプライベートメンバーへのアクセスを実現します.
    void test()
    {
         
    	LaoWang lw;
    	
    	lw.visit1();
    
    	lw.visit2();
    }
    

    同様に、友元はまだ宣言されていないため、クラス内のメンバー関数は別のクラスのプライベートメンバーにアクセスできません.
    キーコード
    friend void LaoWang::visit1();
    

    Buildingクラスで友元メンバー関数を宣言し、コンパイラ**visit 1()**メンバー関数がBuildingクラスの親友であり、Buildingオブジェクトのプライベートメンバーにアクセスできることを示します.
    class Building
    {
         
    	//      ,LaoWang   visit1()   Building     ,    Building     
    	friend void LaoWang::visit1();
    
    public:
    	Building();
    
    	string m_SittingRoom;	//  
    	
    private:
    
    	string m_BedRoom;		//  
    };
    

    次に、メンバー関数を友元として実装するクラスのメンバー関数が、別のクラスのプライベートメンバーにアクセスする完全なサンプルコードを示します.
    #include 
    #include 
    
    using namespace std;
    
    class Building;
    
    class LaoWang
    {
         
    public:
    
    	LaoWang();
    	void visit1();	// visit1()          Building      
    	void visit2();	// visit2()         Building      
    
    	Building *building;
    
    private:
    
    	
    };
    
    class Building
    {
         
    	//      ,LaoWang   visit1()   Building     ,    Building     
    	friend void LaoWang::visit1();
    
    public:
    	Building();
    
    	string m_SittingRoom;	//  
    private:
    
    	string m_BedRoom;		//  
    };
    
    
    LaoWang::LaoWang()
    {
         
    	building = new Building;
    }
    
    void LaoWang::visit1()
    {
         
    	cout << "    LaoWang   visit1()      :" << building->m_SittingRoom << endl;
    	cout << "    LaoWang   visit1()      :" << building->m_BedRoom << endl;
    }
    
    void LaoWang::visit2()
    {
         
    	cout << "    LaoWang   visit2()      :" << building->m_SittingRoom << endl;
    	//cout << "    LaoWang   visit2()      :" << building->m_BedRoom << endl;	//  !        
    }
    
    Building::Building()
    {
         
    	m_SittingRoom = "  ";
    	m_BedRoom = "  ";
    }
    
    void test()
    {
         
    	LaoWang lw;
    	
    	lw.visit1();
    
    	lw.visit2();
    }
    
    int main()
    {
         
    	test();
    	
    	return 0;
    }
    

    出力結果
        LaoWang   visit1()      :  
        LaoWang   visit1()      :  
        LaoWang   visit2()

    以上の内容は私が黒馬のプログラマーの匠心の作|C++教程を学んで0から1まで入門してプログラミングして、プログラミングを学ぶのは難しくない学習ノートで、後日学習して使うのに便利です.