数学演算子のメンバー関数と非メンバー関数


12

私は、行列、ベクトルなどを含む線形代数ライブラリ(長い話、学校の課題です)を書いています。このライブラリを作成する過程で、オブジェクトに対して数学演算を実行する関数を作成します。たとえば、行列の転置、行列の反転、ベクトルの正規化など。

この種の関数の「ベストプラクティス」とは何かに興味がありました。つまり、関数をメンバー関数にするか、非メンバーにするべきでしょうか。(わかりやすくするため/ライブラリの使用目的)

例:

//Member function way:
B = A.transpose();
C = A.inverse();

//Non-member function way:
B = linalg::transpose(A); //Non-member transpose function in linear algebra namespace
C = linalg::inverse(A);

この種の操作に関する標準はありますか?または、少なくとも、これを行う一般的な方法はありますか?私は最初の選択肢に傾いていますが、これが推奨されるかどうか知りたいです。

回答:


7

これはスタイルと好みの問題です。異なる線形代数ライブラリを見てきました

  • メンバー関数を使用してOOPスタイルで記述された

  • 無料の関数のみを使用して非OOPスタイルで書かれた

  • 両方のAPIを提供する

そして、彼ら全員が働いていました。少なくとも、APIは一貫している必要があるため、選択を選択し、これらのスタイルをmix意的に混ぜないようにしてください。


8

会費を避ける:可能な場合は、非会員以外の行事を行うことをお勧めします。

非メンバーの非フレンド関数は、依存関係を最小限に抑えることでカプセル化を改善します。関数の本体は、クラスの非パブリックメンバーに依存することはできません(項目11を参照)。また、モノリシッククラスを分解して分離可能な機能を解放し、結合をさらに減らします(項目33を参照)。操作が特定の型のメンバーであるかどうかを知らないテンプレートを書くのは難しいため、汎用性が向上します[...]

ハーブサッター


1
最後に良い答え:遅いですが、手遅れではありません。;-)別の参照:GotWは#84:モノリス"Unstrung"
デュプリケータ

1

メンバー関数と非メンバー関数の両方には、単なる味のほかに真の利点があります。たとえば、matrixクラスの実装に使用される基になる配列はおそらくでprivateあるため、friendメンバー関数を使用しない限り使用する必要があります。この点で、オブジェクト指向設計の方が優れている場合があります。

ただし、コンピュータサイエンティストは、実際に何をするのかを常に把握せずに、複雑な数式を実装する必要がある場合があることに留意してください。そうする必要があるとき、「視覚的な」結果は元の数式に近くなるため、非メンバー関数を好みます(数式は一般に関数型を使用するため)。

結局、答えはDoc Brownの答えと同じです。それは好みの問題です。つまり、メンバー関数を使用してオブジェクト指向スタイルのライブラリを作成し(記述しやすく、no friend)、非メンバー関数を作成して同じタスクを実行し、単に引数をメンバー関数に転送することを検討できます。これにより、一貫性が保たれ、ユーザーが最適と考えるものを選択できるようになります。


0

問題のステートメントをさらに深く掘り下げると、ある時点で、特定の数学的エンティティを表すカスタムデータ構造を使用することは明らかです。たとえば、n次元配列の平均の行列を表すことができます。あなたの例を詳しく説明するには、

// C way
typedef struct {
    int data[MAX_LEN][MAX_LEN];
} MATRIX;

MATRIX B = transpose(A);

// C++ way
class Matrix; // Forward Declaration
class Matrix {
    int data[MAX_LEN][MAX_LEN];
    public:
        Matrix transpose();
};

Matrix B = A.transpose();

(C ++の例は単純化されており、テンプレートなどを使用できます。)

考慮すべき点は、両方のケースでカスタムデータ構造を使用することの容易さです。言語としてのC ++(または任意のオブジェクト指向)はそれ自体がより強力であり、実装者に利益をもたらす限りライブラリのコンシューマーにも拡張されます。過去にCのみのライブラリを使用したことがありますが、これらのカスタムデータ構造はあっという間に広まったようです!一方、後者では相互運用性を実現するのが簡単です(特別なコンストラクターを使用するのでしょうか?

まとめると、C ++を使用している場合は、オブジェクト指向のアプローチをお勧めします。


5
申し訳ありませんが、あなたの推論には確かな事実はほとんどありません。2つのtranspose例の使いやすさに違いはありません。C ++が簡単な主な理由は、コピーと割り当てのセマンティクスが実際に機能するためです。A = BCでコンパイルできますが、おそらく間違ったことをします。
MSalters

コピーセマンティクスの+1私が理解しようとしていたポイントは、構造(関連する関数)の疎結合セットを使用したオブジェクト(「表現」に対するカプセル化)v / sの使用です。
dotbugfix 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.