フレンド関数なしではオーバーロードできない C++ 演算子はどれですか?
7 に答える
次の場合にのみ、フレンド宣言が必要です。
- 演算子をクラス外のスタンドアロン関数として定義し、
- 実装では、プライベート関数または変数を使用する必要があります。
それ以外の場合は、フレンド宣言なしで任意の演算子を実装できます。これをもう少し具体的にするために...クラスの内外でさまざまな演算子を定義できます*:
// Implementing operator+ inside a class:
class T {
public:
// ...
T operator+(const T& other) const { return add(other); }
// ...
};
// Implementing operator+ outside a class:
class T {
// ...
};
T operator+(const T& a, const T& b) { return a.add(b); }
上記の例で「add」関数がプライベートである場合、後者の例では、operator+
それを使用するためにフレンド宣言が必要になります。ただし、「add」がパブリックの場合、その例で「friend」を使用する必要はありません。フレンドは、アクセスの許可が必要な場合にのみ使用されます。
*クラス内で演算子を定義できない場合があります (たとえば、そのクラスのコードを制御できないが、とにかくその型が左側にある定義を提供したい場合)。 . そのような場合でも、フレンド宣言に関する同じステートメントが当てはまります。フレンド宣言は、アクセスの目的でのみ必要です。演算子関数の実装がパブリック関数と変数のみに依存している限り、friend 宣言は必要ありません。
左側のオペランドがクラス自体ではない演算子。たとえば、関数を定義し、それらをクラス内としてマークcout << somtething
することで実現できます。std::ostream& operator<<(std::ostream& lhs, Something const & rhs);
friend
編集: フレンドシップは必要ありません。しかし、それは物事をより簡単にすることができます。
演算子のオーバーロードと友情は直交する概念です。タイプのプライベートメンバーにアクセスする必要があるときはいつでも関数(任意の関数)を宣言する必要があるfriend
ため、メンバーではない関数として演算子をオーバーロードし、その実装がプライベートメンバーにアクセスする必要がある場合は、次のようにする必要があります。友達。
一般に、sを宣言しない方がよいことに注意してください。これはfriend
、言語で最も高い結合関係であるため、可能な場合は常に、型のパブリックインターフェイスに関して演算子の自由関数オーバーロードを実装する必要があります(演算子を書き直す必要のない型の実装)。場合によっては、パブリックメンバー関数として実装するoperatorX
という観点から、フリー関数として実装することをお勧めします(演算子のオーバーロードについてはこちらをご覧ください) 。operatorX=
クラステンプレートには特定のコーナーケースがあり、プライベートメンバーにアクセスする必要がない場合でも、テンプレートクラス内でテンプレートを定義できるようにするために、テンプレートのフレンドとして無料の関数演算子を宣言することができます。
template <typename T>
class X {
int m_data;
public:
int get_value() const { return m_data; }
friend std::ostream& operator<<( std::ostream& o, X const & x ) {
return o << x.get_value();
}
};
これには、単純で簡単な方法で、テンプレート化されていない単一の関数をフレンドとして定義できるという利点があります。定義をクラステンプレートの外に移動するには、それをテンプレートにする必要があり、構文がより面倒になります。
フレンド機能は必要ありません。演算子をメンバーにしたくない場合 (通常、オペランドを変更しない二項演算子の場合)、フレンドである必要はありません。ただし、それを友達にする理由は2つあります。
- プライベート データ メンバーにアクセスするため、および
- クラス本体で定義するため (メンバーではありませんが)、ADL がそれを見つけられるようにします。
2 番目の理由は主にテンプレートに当てはまりますが、テンプレートの基本クラスで+
andのような演算子を定義するのが一般的
であるため、これが最も一般的なケースです。-
+=
-=
フレンド関数を使用する唯一の理由は、プライベート (保護されたものを含む) メンバー変数と関数にアクセスすることです。
You need to use a friend function when this
is not the left-hand-side, or alternatively, where this
needs to be implicitly converted.
Edit: And, of course, if you actually need the friend
part as well as the free function part.