それでは、演算子オーバーロードの注意点をいくつか挙げておきます。
まず、前々回作ったようなプログラムを書いてみます。
クラスに2つのメンバ変数があり、「+」演算子をオーバーロードして片方のメンバ変数の合計を求め、int型で返すと言うものです。
<sample program cpp063-01>
#include <iostream> class Sample { public: Sample(const int value1, const int value2); int operator+(const Sample &rhs); private: int m_value1; int m_value2; }; int main() { Sample sample1(3, 5); Sample sample2(4, 7); int result = sample1 + sample2; std::cout << "result = " << result << std::endl; return 0; } Sample::Sample(const int value1, const int value2) : m_value1(value1), m_value2(value2) { } int Sample::operator+(const Sample &rhs) { return m_value1 + rhs.m_value1; } |
<実行結果>
result = 7 続行するには何かキーを押してください・・・
コンストラクタ関数で初期値を設定し、お互いのメンバ変数m_value1を加算した結果を表示しています。
このクラスに前回作ったような、演算子のオーバーロードを追加したいと思います。
前回のプログラムでは、クラスにある2つのメンバ変数をそれぞれ加算し、結果をクラスとしてまとめて返すように作りました。
色々追加しなければなりませんが、やってみましょう。
<sample program cpp063-02>
#include <iostream> class Sample { public: Sample(); Sample(const int value1, const int value2); int operator+(const Sample &rhs); Sample operator+(const Sample &rhs); private: int m_value1; int m_value2; }; int main() { Sample sample1(3, 5); Sample sample2(4, 7); int result = sample1 + sample2; std::cout << "result = " << result << std::endl; return 0; } Sample::Sample() : m_value1(0), m_value2(0) { } Sample::Sample(const int value1, const int value2) : m_value1(value1), m_value2(value2) { } int Sample::operator+(const Sample &rhs) { return m_value1 + rhs.m_value1; } Sample Sample::operator+(const Sample &rhs) { Sample temp; temp.m_value1 = m_value1 + rhs.m_value1; temp.m_value2 = m_value2 + rhs.m_value2; return temp; } |
<コンパイル結果>
error C2556: 'Sample Sample::operator +(const Sample &)': オーバーロード関数は、'int Sample::operator +(const Sample &)' と戻り値の型のみが異なります。 note: 'Sample::operator +' の宣言を確認してください error C2371: 'Sample::operator +': 再定義されています。異なる基本型です。 note: 'Sample::operator +' の宣言を確認してください error C2264: 'Sample::operator +': 関数宣言か定義にエラーがあるので、関数が呼び出せません。 error C2088: '+': class に対して正しくありません。 error C2556: 'Sample Sample::operator +(const Sample &)': オーバーロード関数は、'int Sample::operator +(const Sample &)' と戻り値の型のみが異なります。 note: 'Sample::operator +' の宣言を確認してください error C2371: 'Sample::operator +': 再定義されています。異なる基本型です。 note: 'Sample::operator +' の宣言を確認してください error C2084: 関数 'int Sample::operator +(const Sample &)' は既に本体を持っています。 note: '+' の以前の定義を確認してください
コンパイルエラーになりました・・・
演算子オーバーロードも「オーバーロード」ですから、引数の数や型でどの演算子を使うか判断しています。
今回のエラーは、
int operator+(const Sample &rhs); Sample operator+(const Sample &rhs); |
この2つの引数が全く同じですから、区別が付かないのが原因です。
次の注意点は前にも書きましたが、その演算子でイメージ出来ない内容の関数を作ってはいけない、と言う事です。
<sample program cpp063-03>
#include <iostream>
class Sample {
public:
Sample(const int value1, const int value2);
int operator+(const Sample &rhs) const;
private:
int m_value1;
int m_value2;
};
int main()
{
Sample sample1(3, 5);
Sample sample2(4, 7);
int result = sample1 + sample2;
std::cout << "result = " << result << std::endl;
return 0;
}
Sample::Sample(const int value1, const int value2) : m_value1(value1), m_value2(value2)
{
}
int Sample::operator+(const Sample &rhs) const
{
return m_value1 - rhs.m_value1;
}
|
<実行結果>
result = -1 続行するには何かキーを押してください・・・
「+」演算子をオーバーロードしているのに、中身は減算をしています。
このようなオーバーロードは絶対にすべきではありません。
次の例を書きましょう。
↓に一番最初のプログラムがあります。
<sample program cpp063-01>
#include <iostream> class Sample { public: Sample(const int value1, const int value2); int operator+(const Sample &rhs); private: int m_value1; int m_value2; }; int main() { Sample sample1(3, 5); Sample sample2(4, 7); int result = sample1 + sample2; std::cout << "result = " << result << std::endl; return 0; } Sample::Sample(const int value1, const int value2) : m_value1(value1), m_value2(value2) { } int Sample::operator+(const Sample &rhs) { return m_value1 + rhs.m_value1; } |
<実行結果>
result = 7 続行するには何かキーを押してください・・・
これはメンバ変数m_value1を加算する演算子オーバーロードです。
ここにメンバ変数m_value2を加算する演算子オーバーロードを追加したいと考えました。
プロトタイプ宣言を考えると、
int operator+(const Sample &rhs); |
と、すでにある演算子オーバーロードと全く同じです。
こう言った場合、演算子オーバーロードでの対処方法はありません!
あきらめて、メンバ関数で対応してください。