私は今学期に大学でc ++コースを使用したオブジェクト指向プログラミングを行っており、友人の機能について学習していました。
カプセル化とデータの隠蔽が提供するセキュリティをバイパスする能力があるため、私は彼らを本能的に嫌い、インターネット上のいくつかの記事を読み、一部の人々はそれがいくつかの合法的な使用で良いアイデアだと思いました。
OOPの専門家は、C ++のフレンド機能について何と言いますか?ざっと目を通すだけですか、それとももっと学ぶ必要がありますか?
私は今学期に大学でc ++コースを使用したオブジェクト指向プログラミングを行っており、友人の機能について学習していました。
カプセル化とデータの隠蔽が提供するセキュリティをバイパスする能力があるため、私は彼らを本能的に嫌い、インターネット上のいくつかの記事を読み、一部の人々はそれがいくつかの合法的な使用で良いアイデアだと思いました。
OOPの専門家は、C ++のフレンド機能について何と言いますか?ざっと目を通すだけですか、それとももっと学ぶ必要がありますか?
回答:
そのクラスのC ++クラスメンバに関連するすべての関数を作成することは必ずしも便利ではありません。たとえば、スカラー乗算を使用したベクトル代数の実装を想像してください。書きたい:
double a;
Vector v, w;
w = v * a;
メンバー関数でこれを行うことができます:
public class Vector {
...
Vector operator*(double a);
}
しかし、私たちはまた書きたいと思います:
w = a * v
これには無料の機能が必要です。
Vector operator*(double a, Vector v)
の friend
キーワードはこの用法をサポートするために、C ++に追加されました。free関数はVectorクラス実装の一部であり、同じヘッダーで宣言され、同じソースファイルで実装される必要があります。
同様にfriend
、コレクションやイテレータなどの密結合クラスの実装を簡素化するために使用できます。繰り返しますが、同じヘッダーで両方のクラスを宣言し、同じソースファイルに実装します。
inline Vector operator*(double a, Vector v) { return v*a; }
。実際には標準的なソリューション。
inline Vector operator*(double a, Vector v) { return -v*a; }
あり、それでも友情は必要ありません。
フレンド関数は、カプセル化の点でメンバー関数と同じです。ただし、特にテンプレートが関係する場合、より汎用的であるなど、他の利点も提供できます。また、一部の演算子は無料の関数としてのみ指定できるため、メンバーにアクセスを許可する場合は、friend
ます。
friend
あなたが公開したくない何かを強制的に作成するよりも、単一の関数の方が良いです。つまり、1つの関数だけでなく、全世界で使用できるということです。
friend
単一のTUでのみ宣言されているような、「プライベート」な関数も可能です。
「OOPの専門家が言うことは...」それは、主に彼がC ++の専門家であるかどうかに依存します。
OOP ZealotsはC ++を使用しません(Smalltalkを好み、Javaが好きです)。
関数型プログラミングzelotはC ++を使用しません(LISPとその後継を好む)
OOPの専門家のほとんどは、C ++のOOP部分をSmalltalkのように動作させたいという理由だけで、友人機能を嫌います。しかし、C ++はSmalltalkではなく、クラスが必要としない限り関数がクラスのフレンドになれないという非常に単純な理由で、フレンドがカプセル化を破らないことすら理解できません。
そして、「機能性」との間で、ポイントをスタンドからa.fn(b)
してfn(a,b)
違いはありません(ここでfn
友人がある):関係者は同じです。単純に、ある構文は別の構文よりも適している可能性があります。fnがa
and に関して可換であればb
、fn(a,b)
おそらくより適切ですa.fn(b)
(実際にはそうではない「特殊な役割」を持つ外観になります)。
いいえ、違います。「フレンド」は、メンバーシップと同様に、アクセスを許可するための明示的なメカニズムです。(標準準拠のプログラムでは)ソースを変更せずにクラスへのアクセスを許可することはできません。
C ++よくある質問は簡潔です:
可能な場合はメンバーを使用し、必要な場合は友人を使用します。
FAQは、友情についてのより便利な考え方の1つを示しています。
多くの人々は、友人の機能をクラス外の何かと考えています。代わりに、フレンド関数をクラスのパブリックインターフェイスの一部として考えてみてください。クラス宣言のフレンド関数は、パブリックメンバー関数がカプセル化に違反する以上にカプセル化に違反しません。両方とも、クラスの非パブリック部分へのアクセスに関してまったく同じ権限を持っています。
フレンド関数は、ユーザー定義のオペレーター定義に最適です。他の状況でも役立ちますが、フレンドクラスを頻繁に指定することに気づいた場合は、デザインの迂回を行っている可能性があります(コードの作成中に使用するのが良い自己チェックです)。
元の質問の「セキュリティ」ステートメントに注意してください。アクセス修飾子は、ある意味でコンパイラと同じように、誤って間違ったコードを書くことを防ぐためにあります。アクセス修飾子はインターフェースを制限し、クラスを使用するために重要な機能(パブリックおよび保護)、およびメンテナーのクラスをきれいにするための一部として作成された機能(プライベート)を伝達します。修飾子は、プライベートデータを取得する多くの方法があるという点でセキュリティを構成しません。たとえば、クラスとそのサイズへのポインターを取得し、釣りに行きます。
C ++フレンド関数は、次の機能と密接に関連しています。
これは、これらがthis-pointerを持たないため、クラス/オブジェクトの外側にあることを意味します。一方、彼らはしばしばそれらを再びクラスに属するようにするパラメータを取ります。リンクを明確にするいくつかの例を次に示します。
class B;
class A {
public:
friend void f(A &a, B &b);
private:
int m_a;
};
class B {
public:
friend void f(A &a, B &b);
private:
int m_b;
};
void f(A &a, B &b) { /* uses both A's and B's private data */ }
静的関数とフレンド関数の唯一の違いは、フレンド関数が複数のクラスを使用できることです。
C ++でフレンドメカニズムを使用するには、プログラミングのC ++の方法に10〜15年の経験があるプログラマが必要です。したがって、最初はそれを避ける必要があります。高度な機能です。