5

どのようなシナリオで、メンバー関数を「フレンド関数」として宣言しますか?..OOP の「カプセル化」の中心的な概念の 1 つに反する「フレンド関数」は、どのような正確な目的を果たしますか?

4

6 に答える 6

2

複数の C++ クラスまたは関数に物理的にまたがる必要がある抽象化またはインターフェイスを構築しようとしている場合、フレンド関数およびクラスはカプセル化に違反しません! それが友人が発明された理由です。

このようなケースはめったに発生しませんが、異なるクラスや関数を使用して抽象化またはインターフェイスを実装する必要がある場合があります。古典的な例は、ある種の複素数クラスを実装しています。非メンバーの演算子関数は、メインの複素数クラスに関連付けられています。

C++ で CORBA を使ってプログラミングするときにも、これを行ったことを思い出します。CORBA では、CORBA サーバントを実装するために個別のクラスを用意する必要がありました。しかし、ソフトウェアの特定の部分については、これらを 1 つのインターフェイスとして組み合わせる必要がありました。友情により、これら 2 つのクラスが連携して、ソフトウェアの一部にシームレスなサービスを提供することができました。

別のクラスの特定のメンバー関数を自分のクラスのフレンドとしてマークする機能を持つことは、さらに奇妙に思えるかもしれませんが、これはフレンドシップを厳密に制御する方法にすぎません。他のクラス全体をフレンドとして "in" 許可する代わりに、そのメンバー関数の 1 つだけにアクセスを許可します。繰り返しますが、これは一般的ではありませんが、必要なときに非常に役立ちます。

于 2009-02-21T19:44:47.313 に答える
2

フレンド関数は、フレンド クラスを使用するのと同じ理由で使用しますが、(クラス全体ではなく) メンバー関数に基づいて使用します。このスレッドには、いくつかの適切な説明があります。

フレンド関数とクラスはカプセル化に違反しますが、一部のシナリオでは役立ちます。たとえば、テスト ハーネスがクラス内部にアクセスできるようにして、ホワイトボックス テストを実行できるようにすることができます。クラス全体をテスト ハーネスに開放するのではなく、テスト ハーネスに必要な内部にアクセスする特定の関数を開くことができます。これは依然としてカプセル化に違反していますが、クラス全体を開くよりもリスクは低くなります。

フレンド クラスと関数の詳細については、この記事も参照してください。

于 2009-02-21T09:51:56.880 に答える
1

C++ FAQ Liteを参照してください。

フレンドの方が構文的に優れている場合があります (たとえば、クラス Fred では、フレンド関数では Fred パラメーターを 2 番目にすることができますが、メンバーは Fred パラメーターを 1 番目にする必要があります)。フレンド関数のもう 1 つの適切な使用法は、2 項中置算術演算子です。たとえば、aComplex + aComplex は、aFloat + aComplex も許可したい場合は、メンバーではなくフレンドとして定義する必要があります (メンバー関数は、左側の引数の昇格を許可しません。これは、オブジェクトのクラスが変更されるためです)。メンバー関数呼び出しの受信者)。

于 2009-02-21T17:46:34.757 に答える
0

パブリック/プライベート/保護された保護レベルでは、実際の状況では十分でない場合があります。したがって、メソッドをパブリックにアクセス可能にする必要なしに役立つ小さなget-out句を指定します。

私は個人的に、Javaが「パッケージ」保護レベルを使用するのと同じ方法でこれを使用します。
同じパッケージにアクセスが必要なクラスがある場合は、友達の使用を検討します。それが別のパッケージのクラスである場合、なぜこの他のクラスにアクセスして私のデザインを見る必要があるのか​​疑問に思います。

于 2009-02-21T10:08:12.223 に答える
0

私が関連していると思う 1 つのポイント: メンバー クラスは、包含クラスのプライベート パーツにアクセスできます。これは、「友達」の代わりになる場合があります。

class A
{
private:
  int b;
public:
  class MemberNotFriend {
  public:
    static void test() {
      A a;
      a.b = 0;
    }
  };


};


void test()
{
  A::MemberNotFriend::test();
}
于 2009-05-21T19:51:50.657 に答える
0

これは、フレンド関数を使用する方法の簡単で具体的な例です。

各スプライト オブジェクトが X、Y 位置などの情報をプライベート メンバーとして格納するゲームがあります。ただし、ゲーム オブジェクトをレンダリングから分離したいと考えています。ゲーム オブジェクトは、レンダリング方法の正確な詳細を必要としません。ゲームオブジェクトはゲームの状態のみを保存し、このゲームの状態はさまざまな方法でレンダリングできます。

したがって、ゲーム オブジェクト クラスにはフレンド関数 render() があります。render() 関数はゲーム オブジェクト クラスの外部で実装されますが、ゲーム オブジェクトをレンダリングするために必要に応じて X、Y 位置 position membefrs にアクセスできます。

于 2009-12-07T10:11:14.243 に答える