重複の可能性:
C++で「友達」を使用する必要があるのはいつですか?
私はC++を磨き上げていました(私はJava開発者です)で、friend class
しばらく忘れていたキーワード。これは、台所の流しの一部にすぎない機能の1つですか、それともバニラゲッターだけでなく、これを行うのに十分な理由がありますか?データにアクセスできるユーザーが制限されるという違いは理解できますが、これが必要になるシナリオは考えられません。
注:同様の質問を見たことがありますが、具体的には私が尋ねているのは、これは、あなたが何をしているか理解するまでコードを見ている人を混乱させることを除いて、本当の価値を追加しない高度な機能だけなのですか?
私は、friendキーワードが賢明に使用されれば、カプセル化を改善できると言うコメントに同意します。フレンドクラスの最も一般的な(正当な!)使用法はテストであることを追加します。テスタークラスに、他のクライアントクラスよりも高度なアクセスを許可することができます。テスタークラスは、他のクラスから意図的に隠されている内部の詳細を確認するのに十分な理由がある場合があります。
私の経験では、実際にデータのカプセル化を強化するために友人(または少し似ているミュータブル)が、カプセル化を解除するために使用される頻度と比較すると、まれです。
それが私に役立つことはめったにありませんが、それを使用する場合、以前は単一のクラスであったクラスを、いくつかの一般的なデータ/機能にアクセスする必要がある2つの別々のクラスに分割しなければならなかった場合です。
Outlaw Programmerのコメントに応答するように編集します。これについては完全に同意します。クラスを分割した後でクラスを友だちにすることとは別の1つのオプションは、パブリックアクセサーを作成することです。フレンドリークラスは、カプセル化が不適切に使用されているのを見たことがあるため、カプセル化が何らかの形で壊れていると考える人もいると思います。まれに、コードが正しく使用されているコードを見たことがない人も多いでしょう。私はそれを述べるあなたの方法が好きです-親しみやすさは、クラスを分割することを許可しないこととすべてを一般にアクセス可能にすることの間の良い中間点です。
David Thornleyに対応するための編集:C++がこのようなことを可能にする柔軟性は、C++に入った設計上の決定の結果であることに同意します。そのため、柔軟な言語で一般的に良いスタイルと悪いスタイルを理解することがさらに重要になります。 Javaの視点では、フレンドクラスを提供しないようにすべきではありませんが、C++プログラマーとして、これらの非常に柔軟だが誤用される言語構造の適切な使用を定義することはコミュニティとしての私たちの責任です。
Tomに応答するための編集:Mutableは必ずしもカプセル化を解除するわけではありませんが、実際の状況で見たmutableキーワードの使用法の多くはカプセル化を解除します。そもそも実際にmutableの適切な使用法を見つけて理解します。
あるクラス(ファクトリ)が別のクラス(タイプ)のインスタンスを作成する必要がある場合。 Typeのコンストラクターをプライベートにして、ファクトリのみがTypeオブジェクトを作成できるようにすることができます。チェックをバリデータとして機能する他のクラスに委任したい場合に便利です。使用シナリオは1つだけです。
追伸C#の "friend"キーワードが本当にありません...
具体的なインスタンスはクラスファクトリであり、1つのクラスが別のファクトリクラスを通じてのみ作成されるようにするため、コンストラクタをプライベートにし、ファクトリクラスを生成されたクラスのフレンドにします。
これは、2インチ12ポイント3/4インチドライブソケットのようなものです-それほど一般的ではありませんが、必要なときに、あなたがそれを持っていることを非常に嬉しく思います。
Mementoデザインパターン の支援
いくつかの例を挙げますが、カプセル化の理由を無視することなく、Friendクラスを正当に使用できます。
MyClassはGeneralClassを継承しています。 MyClassが大きくなったため、MyClassの一部の機能をカプセル化するHelperClassを作成しました。ただし、HelperClassは、その機能を適切に実行するためにGeneralClassのいくつかの保護された機能にアクセスする必要があるため、HelperClassをMyClassの友達にします。
これは、保護された関数を公開するよりも優れています。保護された関数をすべての人が利用できる必要はないためです。ただし、コードをOOPのように整理することで、MyClassが複雑になりすぎないようにすることができます。 HelperClassは継承によって具体的にMyClassに関連付けられていませんが、コードに組み込まれ、設計上は「フレンド」として、それに何らかの論理的な接続があるため、理にかなっています。
友情は、同じ抽象化またはインターフェースを提供するために連携して機能する複数のクラスや関数がある場合に使用されます。古典的な例は、ある種の数値クラスの実装であり、すべての非メンバー演算子関数(*、-、+、<<など)は、数値クラスのプライベートデータで作業できるように友情を与えられています。
このような使用例は、ややまれですが、実際に存在するため、friendは非常に役立ちます。
friend
構文を、まれに使用される言語の機能の1つと見なしますが、それが役に立たないわけではありません。 friend
クラスを作成する必要があるいくつかのパターンがあります。それらの多くは、このサイトの右側の「関連」バーにすでにあります。 ====>
フレンドクラスとは、他のクラスからの変数の値にアクセスすることを誰もが知っているため、主に値を使用するために使用されるため、他のクラスの値をメイン関数に返し、次にメインを必要なクラスメンバー関数に返す必要はありませんが、クラスである問題が他のクラスの友達である場合、友達クラスはそのクラスの下にある必要があります
私は常に(そして唯一)プライベートメソッドのユニットテストにフレンドを使用しています。私がこれを行うと想像できる他の唯一の方法は、パブリックインターフェイスに多くのテストメソッドをロードすることです。
このようなもの:
class cMyClassTest;
class cMyClass
{
public:
.....
private:
friend cMyClassTest;
int calc(); // tricky algorithm, test carefully
};
class cMyClassTest
{
public:
int test_calc()
{
cMyClass test;
....
int result = test.calc();
if( result == 42 )
return 1;
return 0;
}
};