c+++友元関数と友元類の深度解析


友元関数と友元類の必要性:クラスはパッケージと情報隠蔽の特性を持つ。クラスのメンバー関数だけがクラスのプライベートメンバーにアクセスできます。他の関数はプライベートメンバーにアクセスできません。非メンバ関数は、クラスの共有メンバーにアクセスすることができますが、データのメンバーを共有と定義すると、また隠し機能を破壊します。また、いくつかの場合、特に、いくつかのメンバー関数に対して何度も呼び出しを行う場合、パラメータ伝達、タイプ検査、セキュリティチェックなどが時間オーバヘッドを必要とし、プログラムの動作効率に影響を与えることが見られる。上記の問題を解決するために、友元を利用する案を提案します。友元はクラスの外部を定義する普通の関数ですが、クラス内で説明する必要があります。このクラスのメンバー関数と区別するために、説明の前にキーワードfriendを追加します。友達はメンバー関数ではありませんが、クラスのプライベートメンバーにアクセスできます。友元の役割は、プログラムの動作効率を向上させることにあるが、非メンバ関数がクラスのプライベートメンバにアクセスできるように、クラスのパッケージ性と隠し性を破壊する。友元は、友元関数と呼ばれる関数でありうる。友元は同じクラスでもいいです。このクラスは友元類と呼ばれています。
友元関数友元関数の特徴は、クラス内のプライベートメンバにアクセスできる非メンバ関数である。友達関数は文法的に見て、普通の関数と同じです。つまり、定義と呼び出しは普通の関数と同じです。以下の例を挙げて、友元関数の応用を説明します。

#include "iostream"
#include "cmath"
using namespace std;
class Point
{
private:
 double x,y;
public:
 Point(double xx, double yy) { x=xx; y=yy; }
 void Getxy();
 friend double Distance(Point &a, Point &b);  //friend , ,
};
void Point::Getxy()
{
 cout<<"("<<x<<","<<y<<")"<<endl;
}
double Distance(Point &a, Point &b)
{
 double dx = a.x - b.x;  //
 double dy = a.y - b.y;
 return sqrt(dx*dx+dy*dy);
}
int main(void)
{
 Point p1(3.0, 4.0), p2(6.0, 8.0);
 p1.Getxy();    //
 p2.Getxy();
 double d = Distance(p1, p2);  // , ,
 cout<<"The distance is "<<d<<endl;
 system("pause");
 return 0;
}
は、このプログラムのPointクラスに、説明の前にfriendキーを追加して、メンバー関数ではなく、友元関数を識別する友元関数Distance()を示していると説明しています。その定義方法は、所属するクラスを指摘する必要がないので、メンバー関数の定義とは異なり、通常の関数と同じである。しかし、このクラスのプライベートメンバを参照することができます。関数はa.x、b.x、a.y、b.yは、オブジェクトを介して参照されます。友元関数を呼び出す時も、普通の関数と同じように、メンバー関数のように呼ばないでください。この例では、p 1.Getxy()とp 2.Getxy()はメンバー関数の呼び出しであり、オブジェクトで表します。Distance(p 1,p 2)は、直接的に呼び出します。オブジェクト表示は不要です。パラメータはオブジェクトです。
友元類友元は前に述べた関数以外に、友元はクラスでもいいです。つまり、一つの種類は別の種類の友元になります。一つのクラスが別のクラスの友達として働くとき、これはこのクラスのすべてのメンバー関数が別のクラスの友達関数であることを意味します。(1)友元関係は引き継がれません。2)友元関係は一方的で、交換性がない。クラスBがクラスAの友達である場合、クラスAはクラスBの友達とは限らず、クラスに該当する声明があるかどうかを確認します。3)友元関係には伝達性がない。クラスBがクラスAの友元である場合、クラスCはBの友元であり、クラスCは必ずしもクラスAの友元ではなく、クラス中に該当する申明Cの中でAがその友元類であるかどうかを確認すると、最も基本的なのはAがCのprvate方法または対象を使用することができることである。AはBのベースクラスで、CはDのベースクラスです。ABCDには次のような関係があります。1.Bに追加された方法はCのプライベートメンバ2.Bにアクセスできません。Aから継承された方法はCのプライベートメンバ3.Aにアクセスできます。DにはCから継承されたプライベートメンバしか訪問できません。Dに追加されたプライベートメンバはアクセスできません。
まとめてみます。(1)友元関係は引き継げませんが、既存の方法でアクセス権限は変わりません。2)基本的な方法を書き換えるとアクセス権限が変更される(3)友元関係が伝達性を持たない場合、クラスBはクラスAの友元、クラスCはBの友元、クラスCはクラスAの友元とは限らない。