2017-03-29 16 views
6

以前は、クラスのfriend関数と同様に、メンバ関数としてC++の演算子のオーバーロードについて学びました。しかし、私は両方のテクニックを使用してC++で演算子をオーバーロードする方法を知っています。しかし、私はまだ混乱しています**どちらが良い**ですか?演算子をオーバーロードするためのメンバー関数またはフレンド関数ですが、どちらを使うべきですか、なぜですか? 私を案内してください!あなたの応答は非常に高く評価されます。私はあなたの答えに喜んで感謝します。オペレータオーバーロードの友人vsメンバ関数C++

+2

グローバルな非フレンド機能はどうですか?まあ、いずれにせよ、常にメンバーよりグローバルに行くことを好みます。 – DeiDei

+0

グローバルな非友人機能ですか?私はオーバーロードされた演算子は、友人やメンバーの関数だけになると思った。しかし、ありがとう!私はそれについても検索します。 –

+0

'friend'は、関数にクラスの' private'と 'protected'メンバへのアクセス権を与えるためだけに必要です。そうでなければ、それが必要でない場合、 'friend'も必要ではありません。 – DeiDei

答えて

0

これは固定されたルールではないので、私はちょうど私の意見を述べます:可能であれば、演算子のオーバーロードにメンバー関数を使用してください。これの主な理由は、演算子がクラスの不可欠な部分であるとみなし、クラスのロジックがよりローカライズされていることです。

オペレータのオーバーロードに自由な機能を使用する理由は、クラスを可能な限りリーンに保つことです(必要なときにのみフレンドを使用する)。

オペレータはメンバーになることができないため、その場合は議論の余地がありません。主にメンバー関数は、常に可能ではない第1のパラメータとしてクラスインスタンスを有する(例えば、オペレータ< </i)。

2

メンバーの機能と友人は、どちらか一方のみを選択する必要があります。両方を使用すると、例えば、コードを実装してコードを複製し、それを呼び出すことによってコードを複製しないようにすることができます。

struct A 
{ 
    A operator+=(A const & second); 
}; 

A operator+(A const &first, A const &second) 
{ 
    A temp(first); 
    temp += second; 
    return temp; 
} 

しかし、あなたは機能のために選択したい場合は、それがメンバーかどうかにする必要がある場合は、ここで私が従うルールである場合:非メンバ関数を実装する(friendかない)ときは、私はバイナリ演算子を持って、私たちが期待する対称性を尊重します。例:Aintを暗黙的に(コンストラクタがintである)に変換する可能性があります。もしメンバー関数があれば、結果はどうなりますか?

A a1, a2; 
a1 + a2; // OK 
a1 + 42; // OK 
42 + a2; // KO 

無料の機能で、結果があります。

A a1, a2; 
a1 + a2; // Ok 
a1 + 42; // Ok 
42 + a2; // Ok 

この可能性を使用する具体的なC++クラスは、std::stringです。

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string s {"World"}; 
    // Works with absolutely no problem. 
    std::string chaine = "Hello " + s; 
    std::cout << chaine << std::endl; 
} 

結論として、ここにはgood linkがあります。

+0

ありがとうございました:-) これはロットを助けました:-) –

3

「メンバーまたは友人」ではなく「メンバーまたは非会員」です。
(フレンドシップは頻繁に過度に使用され、通常学校では早すぎると教えられます)

これは、フリー関数が呼び出すことができるパブリックメンバー関数をいつでも追加できるためです。例えば

class A 
{ 
public: 
    explicit A(int y) : x(y) {} 
    A plus(const A& y) const { return A{x + y.x}; } 
private: 
    int x; 
}; 

A operator+(const A& lhs, const A& rhs) { return lhs.plus(rhs); } 

選択する方法について:オペレーターがその左側のオペランドとしてクラスのインスタンスを取らない場合、それはそれ以外の場合はだ、自由な関数でなければなりません個人的な味覚の問題(または、あなたが一人でないならコーディングの基準)。

例:対応する突然変異演算子(等++=)を有するオペレータについて

// Can't be a member because the int is on the left. 
A operator+ (int x, const A& a) { return A{x} + a; } 

、それは非会員としての部材と他方として変異演算子を行うことが一般的だ:

class B 
{ 
public: 
    explicit B(int y) : x(y) {} 
    B& operator+= (const B& y) { x += y.x; return *this; } 
private: 
    int x; 
}; 

B operator+(B lhs, const B& rhs) { return lhs += rhs; } 

ていますが、もちろん、あまりにもこれを綴ることができます。

class C 
{ 
public: 
    explicit C(int y) : x(y) {} 
    C& add(const C& y) { x += y.x; return *this; } 
private: 
    int x; 
}; 

C& operator+=(C& lhs, const C& rhs) { return lhs.add(rhs); } 
C operator+(C lhs, const C& rhs) { return lhs += rhs; } 
+0

ありがとうたくさん:-) 素晴らしい情報サー! –

1

味の問題はそれほどではありませんが、いくつかのユースケースでは明らかに2つの方法のいずれかが必要です。

オペレータが設計中のクラスのメンバのみを引数として取る場合、カプセル化はメンバ関数を使用して投票します。例:二つのオブジェクトの追加:あなたが書いているクラスのメンバは、オペレータの2番目の引数があり、反対に

class A { 
    ... 
    A operator + (const class A& other); // naturally a member function 
    ... 
}; 

、あなただけではフレンド関数

std::outstream& operator << (std::outstream& out, const class A& a); 

class A { 
    ... 
    friend std::outstream& operator << (std::outstream& out, const class A& a); // must be friend here 
}; 

を使用することができますほとんどの場合std::outstreamのメンバーかもしれませんが、クラスが標準のC++ライブラリで作成された場合、Aクラスは存在しませんでした...

+0

ありがとうございました:-) 私はあなたから新しい何かを学んだ:-) –

関連する問題