10

私は現在、オーバーロードされた演算子を含むユーティリティクラスを作成しています。それらをメンバーまたは非メンバー(friend)関数にすることの長所と短所は何ですか?それともそれはまったく重要ですか?たぶん、これにはベストプラクティスがありますか?

4

6 に答える 6

21

「C++ コーディング標準: 101 のルール、ガイドライン、およびベスト プラクティス」を使用します。非メンバー関数として実行できる場合は、非メンバー関数として (同じ名前空間で) 実行します。

理由の 1 つは、暗黙的な型変換を使用した方がうまく機能することです。例: オーバーロードされた operator* を持つ複雑なクラスがあります。2.0 * aComplexNumber を書きたい場合は、operator* を非メンバー関数にする必要があります。

もう 1 つの理由は、カップリングが少ないことです。非メンバー関数は、メンバー関数よりも密接に結合されていません。これはほとんど常に良いことです。

于 2010-01-08T07:31:04.140 に答える
17

各オペレーターには独自の考慮事項があります。たとえば、 << 演算子 (ビット シフトではなくストリーム出力に使用される場合) は、最初のパラメーターとして ostream を取得するため、クラスのメンバーにすることはできません。加算演算子を実装している場合は、おそらく両側で自動型変換の恩恵を受けたいと思うでしょう。したがって、非メンバーも使用します...

継承による特殊化の許可に関して、一般的なパターンは、仮想メンバー関数に関して非メンバー演算子を実装することです (たとえば、operator<< は、渡されるオブジェクトで仮想関数 print() を呼び出します)。

于 2009-12-15T06:16:22.173 に答える
5

ストリーミング演算子 (<< と >>) の実装を計画している場合、オブジェクトは演算子の左側にあるため、それらは非メンバー メソッドになります。

->、()、または [] の実装を計画している場合、それらは当然メンバー メソッドです。

他のもの (比較と数学) については、 Boost.Operatorsをチェックしてください。本当に役に立ちます。

たとえば、次の演算子を実装する場合:

MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);

次のように書くだけです。

class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
  MyClass& operator+=(int);
private:
};

2operator+は非メンバーとして自動的に生成され、自動変換の恩恵を受けることができます。そして、それらは効率的に実装されるoperator+=ため、コードを 1 回だけ記述します。

于 2009-12-15T10:23:39.567 に答える
3

op を実装している場合は、おそらく op= を実装する必要があります。つまり、+ 演算子をオーバーロードしている場合は、+= を実装する必要があります。ポストインクリメントまたは + 演算子のオーバーロードを行っている場合は、const をオブジェクトに返すようにしてください。したがって、演算子 + をオーバーロードする場合は、それを非メンバー演算子として実装し、その中で += 演算子を使用します。たとえば。

const A operator+(const A& lhs, const A& rhs)
{
   A ret(lhs);
   ret += rhs;
   return ret;
}
于 2009-12-15T06:41:53.713 に答える
3

二項演算子の場合、メンバー関数の制限の 1 つは、左側のオブジェクトがクラス型でなければならないことです。これにより、演算子の対称的な使用が制限される可能性があります。

単純な文字列クラスを考えてみましょう:

class str
{
public:
    str(const char *);
    str(const str &other);
};

operator+ をメンバー関数として実装すると、 whilestr("1") + "2"はコンパイルされますが、コンパイルされ"1" + str("2")ません。

しかし、operator+ を非メンバー関数として実装すると、これらのステートメントは両方とも有効になります。

于 2009-12-15T06:56:10.067 に答える
0

ベストプラクティスのようなものはありませんが、オーバーロードしている演算子によって異なります..

例えば。

  1. >><<はメンバー関数としてオーバーロードできません。

  2. 次のようにしたいとします: obj1 = 2 * obj2次に、非メンバー関数に進みます。

二項演算子の場合、メンバー関数のオーバーロードは1 つのパラメーターのみを受け取ります (呼び出しオブジェクトは暗黙的に渡されます) が、非メンバー関数は 2 つのパラメーターを受け取ります。

于 2009-12-15T06:15:54.623 に答える