C++のfriend詳細解析


C++の友元メカニズムはクラスの非公有メンバーが1つのクラスまたは関数によってアクセスされることを可能にし、友元はタイプによって3種類に分けられる:普通の非クラスメンバー関数は友元として、クラスのメンバー関数は友元として、クラスは友元とする.友元には、友元の宣言と友元の定義が含まれます.友元の宣言はexternにデフォルト設定されています.つまり、友元クラスまたは友元関数の役割ドメインは、そのクラス定義を含む役割ドメインに拡張されているので、クラスの内部で友元関数を定義しても関係ありません.
友元は、友元関数と呼ばれる関数であってもよい.友元は、友元類と呼ばれるクラスであってもよい.メタ関数の特徴は、クラス内のプライベートメンバーにアクセスできる非メンバー関数です.友元関数は文法的に一般関数と同様,すなわち定義的および呼び出し的に一般関数と同様である.
友元関数の実装はクラス外で定義できますが、クラス内で宣言する必要があります.
友元関数は、クラスのプライベートメンバーに直接アクセスできる非メンバー関数です.クラス外に定義された一般的な関数です.クラスには属しません.
ただし、クラスの定義に宣言する必要があります.宣言するときは、友元の名前の前にキーワードfriendを付けるだけです.
クラスにはカプセル化と情報隠蔽の特性があることが知られています.クラスのメンバー関数のみがクラスのプライベートメンバーにアクセスでき、プログラム内の他の関数はプライベートメンバーにアクセスできません.非メンバー関数はクラス内の共有メンバーにアクセスできますが、データ・メンバーを共有として定義すると、非表示のプロパティが破壊されます.また、特定のメンバー関数を複数回呼び出す場合、パラメータ伝達、タイプチェック、セキュリティチェックなど、時間のオーバーヘッドが必要になるため、プログラムの実行効率に影響を与える場合があります.
上記の問題を解決するために,友元を用いる案を提案した.友元はクラスの外部に定義された一般的な関数ですが、クラス内で説明する必要があります.このクラスのメンバー関数と区別するために、説明の前にキーワードfriendを付けます.友元はメンバー関数ではありませんが、クラス内のプライベートメンバーにアクセスできます.友元の役割は、プログラムの実行効率を向上させることです(すなわち、タイプチェックやセキュリティチェックなどの時間的なオーバーヘッドを削減することです).しかし、クラスのパッケージ性と非表示性を破壊し、非メンバー関数がクラスのプライベートメンバーにアクセスできるようにします.
1.通常の非メンバー関数の友元
#include "cmath"
#include "iostream"
using namespace std;
class Point
{
public:
      Point(double xx,double yy)
      {
          x=xx;
          y=yy;
      }
      void GetXY();
      friend double Distance(Point &a,Point &b);
protected:
private:
      double x,y;
};
void Point::GetXY()
{
     //cout<x<y<

説明:プログラム内のPointクラスには、説明の前にfriendキーを付けて、メンバー関数ではなく、友元関数であることを示す友元関数Distance()が説明されています.その定義方法は、メンバー関数の定義とは異なり、通常の関数定義と同様です.これは、属するクラスを指摘する必要がないためです.ただし、クラス内のプライベートメンバーを参照できます.関数体のa.x、b.x、a.y、b.yは、オブジェクトによって参照されるクラスのプライベートメンバーです.友元関数を呼び出す場合も、通常の関数の呼び出しと同様に、メンバー関数のように呼び出さないでください.本例では、p 1.Getxy()とp 2.Getxy()これは、オブジェクトで表すメンバー関数の呼び出しです.一方、Distance(p 1,p 2)は、オブジェクト表示を必要とせず、そのパラメータがオブジェクトである友元関数の呼び出しである.△このプログラムの機能は、2点座標が既知であり、2点の距離を求めることである.
次に、上記のコードを入力、出力ストリームの再ロードします.
#include 
#include 
using namespace std;
class Point
{
public:
      Point(double xx,double yy)
      {
           x=xx;
           y=yy;
      }
      void GetXY();
      friend double Distance(Point &a,Point &b);
     friend ostream &operator <x<y<

2.類を友元とする
クラスは、友元として友元クラスと元のクラスとの相互依存関係に注意する必要があります.友元クラスで定義された関数が元のクラスのプライベート変数に使用されている場合は、友元クラス定義のファイルに元のクラス定義のヘッダファイルを含める必要があります.ただし、元のクラスの定義(メタクラス宣言を含むクラス)では、メタクラスのヘッダファイルを含める必要はありません.また、メタクラスの宣言自体が宣言であるため、クラス定義の前にメタクラスを宣言する必要はありません.
//A.h  
#pragma once  
#include   
using namespace std;  
class A  
{  
	//friend class B;  //               
public:  
	~A(void);  
	A();
private:    
	int m_nItem;
}; 
//A.cpp
#include "A.h"

A::A()
{
	m_nItem =3;
}

A::~A(void)
{
}
//B.h
#pragma once  

class B  
{  
public:  
	B(void);  
	~B(void);  
	int func();  
};  
//B.cpp
#include "StdAfx.h"

#include "B.h"  
#include "A.h" //must include A.h 
#include 


B::B(void)
{
}

B::~B(void)
{
}

int B::func()  
{  
	cout<

3.クラスメンバー関数を友元関数として使用
これは少し複雑です.クラスメンバー関数を友元として使用するため、友元を宣言するときにクラス制限子を使用する必要があります.友元関数を含むクラスを定義する必要がありますが、友元の関数を定義するときは、元のクラスを事前に定義する必要があります.通常の方法では、友元関数を含むクラスを定義してから、元のクラスを定義します.この順序は乱れません.(友元類の場合、このような必須はありません)は、次のようになります.
//A.h
#pragma once
#include "B.h"
class A
{
friend int B::func(A xx);
public:
	A(void):mx(20),my(30){}
	~A(void){}
private:
	int mx;
	int my;
};
//B.h
#pragma once
class A;
class B
{
public:
	B(void);
	~B(void);
	int func(A xx);
};
//B.cpp
#include "B.h"
#include "A.h"

B::B(void)
{
}
B::~B(void)
{
}
int B::func(A xx)
{
	return xx.mx * xx.my;
}
//main.cpp
#include "A.h"
#include "B.h"
#include 
using namespace std;
void main()
{
	A a;
	B b;
	cout<

4.友元は相互性を持たず、単項性しか持たない
クラスBがクラスAの友元であれば、クラスAは必ずしもクラスBの友元ではなく、クラスに相応の声明があるかどうかを見なければならない.
5.友元は引き継がれない
BはAの友元類、CはBの子類で、CがAの友元であることを推測できない.
6.友元は伝達性がない
BはAの友元、CはBの友元で、CがAの友元であることを推測することができません
7.友元関数の使い方
C++を用いて単一例モードを実現する場合,友元関数を用いてオブジェクトをインスタンス化することができる.次にクラスのコンストラクション関数とコンストラクション関数をプライベート関数に設計します.
 
class CMySingleton
{
public:
    friend CMySingleton& InstanceMEC();

private:
    CMySingleton() {};
    CMySingleton(const CMySingleton &lxSington) {};
    ~CMySingleton(){};
};

CMySingleton& InstanceMEC()
{
    //    InstanceMEC()  ClxSingletonMEC     ,              .         
    static CMySingleton Instance; 
    return Instance;
}