正直なところ、そのような決定を下す唯一の理由は、構文上の利便性と伝統だと思います。2つの違いが何であるか(そうでないか)、そして決定を下すときにこれらの違いがどのように重要であるかを示すことによって、その理由を説明します。
非会員の友達機能と公開会員機能にはどのような違いがありますか?あまりない。結局のところ、メンバー関数は、非表示のthis
パラメーターとクラスのプライベートメンバーへのアクセスを備えた単なる通常の関数です。
// what is the difference between the two inv functions?
// --- our code ---
struct matrix1x1 { // this one is simple :P
private:
double x;
public:
//... blah blah
void inv() { x = 1/x; }
friend void inv(matrix1x1& self) { self.x = 1/self.x; }
};
matrix1x1 a;
// --- client code ---
// pretty much just this:
a.inv();
// vs this:
inv(a);
void lets_try_to_break_encapsulation(matrix1x1& thingy) {
thingy.x = 42; // oops, error. Nope, still encapsulated.
}
どちらも同じ機能を提供し、他の機能が実行できることを変更することはありません。同じ内部が外の世界にさらされます。カプセル化に関しては違いはありません。プライベート状態を変更するフレンド関数があるため、他の関数が異なる方法で実行できることはまったくありません。
実際、ほとんどのクラスを非メンバーフレンド関数(仮想関数と一部のオーバーロードされた演算子はメンバーである必要があります)として記述でき、まったく同じ量のカプセル化を提供します。ユーザーはクラスを変更せずに他のフレンド関数を記述できません。フレンド関数以外の関数はプライベートメンバーにアクセスできます。どうしてそんなことをしないの?これは、C ++プログラマーの99.99%のスタイルに反するものであり、そこから得られる大きな利点がないためです。
違いは、関数の性質とそれらの呼び出し方法にあります。メンバー関数であるということは、そこからメンバー関数へのポインターを取得できることを意味し、非メンバー関数であるということは、それへの関数ポインターを取得できることを意味します。しかし、それが関連することはめったにありません(特に、周りのようなジェネリック関数ラッパーの場合std::function
)。
残りの違いは構文です。D言語の設計者は、全体を統合して、のようなオブジェクトを渡すことでメンバー関数を直接呼び出すことができinv(a)
、のような最初の引数のメンバーとしてフリー関数を呼び出すことができると言うことにしましたa.inv()
。そして、それか何かのために突然ひどくカプセル化されたクラスはありません。1
質問の特定の例に対処するにはinv
、メンバーであるか非メンバーである必要がありますか?上で概説した親しみやすさの議論のために、私はおそらくそれをメンバーにするでしょう。非スタイル的には、違いはありません。
1。これはC++で発生する可能性は低いです。これは、現時点では重大な変更であり、実質的なメリットがないためです。極端な例として、matrix1x1
両方の呼び出しがあいまいになるため、上記で記述したクラスが壊れます。