• ベストアンサー

二項演算子のオーバーライドについて

a-kumaの回答

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

それは、あなたがやっているのが「メソッドのオーバーライド」ではなく、 「関数のオーバーロード」だからです。 クラスの宣言の中に実装を書いているので分かり難いですが、実装を 分離すると、 class clsText { ... friend clsTest operator + (const clsTest oP1,const clsTest oP2); friend ostream& operator << (ostream& oOutStream, const clsTest oT); }; clsTest operator + (const clsTest oP1,const clsTest oP2) {   return clsTest(oP1.m_dNum+oP2.m_dNum); } ostream& operator << (ostream& oOutStream, const clsTest oT) {   return oOutStream << "T(" << oT.m_dNum <<")"; } となります。両方ともグローバルなスコープを持つ + と << を 追加しているだけです。グローバルな関数の実装をしているのです から、private なメンバを触るためには friend 宣言が必要になります。 operator+ は、メソッドのオーバーライドでも記述できます。 class clsText { ... clsTest operator + (const clsTest oP2); }; clsTest clsText::operator + (const clsTest oP2) {   return clsTest(m_dNum + oP2.m_dNum); } 違いが分かりますか?

nakashi
質問者

補足

では逆に Add関数をグローバルにする方法は? class clsTest { private: double m_dNum; public: clsTest() : m_dNum(0) {} clsTest(double dNum) : m_dNum(dNum) {} void Add(clsTest oT1,clsTest oT2) { m_dNum = oT1.m_dNum + oT2.m_dNum; } // friend clsTest Add(clsTest oT1,clsTest oT2){} }; void main() { clsTest oT1(2); clsTest oT2(5); clsTest oT3; oT3.Add(oT1,oT2); // oT3 = Add(oT1,oT2) こう書きたい } #クラスの基本的な理解が欠けているみたいで、すみません #このへんのことが書いてある おすすめの本があれば教えて下さい

関連するQ&A

  • ポインタの入出力演算子?[C++]

    入出力演算子を使ったコードを書いているのですが わからないところがあるので教えてください。 friend std::ostream& operator <<( std::ostream& out, const Box can ); friend std::istream& operator >>( std::istream& in, Box & can ); friend std::ostream& operator <<( std::ostream& out, const Box * can ); friend std::istream& operator >>( std::istream& ins, Box * & can ); このうち上の二つの普通の演算子はちゃんと動いている のですが、下の二つはどのようにすればいいのかわかりません。 下のコードのようにポインタを使って入出力したいんですが・・・ Box * ptrCan = NULL; cout << ptrCan; ptrCan = &t; cout << ptrCan; cin >> ptrCan; cout << ptrCan;

  • 添字演算子

    #include <iostream> class hoge{ private: int a; public: hoge(){ a = 0; } int operator+(int fuga){ a = a + fuga; return a; } int operator[](int fuga){ return 1; } }; int main(){ hoge* p; p = new hoge; std::cout << ((*p) + 5) << std::endl; std::cout << ((*p)[1] ) << std::endl; // 5 // 1 // std::cout << ((*p) [] 1); エラーです。何故ですか? }

  • C++での入出力演算子のオーバーロード

    C++学習者です。Visual Studio 2015 を使っています。 入力演算子>> と出力演算子<<をオーバーロードする関数をfriend としてクラス定義の中に書きましたが、”メンバーではありません” というメッセージが出てきてコンパイルできません。 エラー番号はC2039です。 何回調べても原因がわからないので、詳しい方にお聞きしたいです。 どうかよろしくお願いいたします。 ヘッダーファイルと関数定義ファイル、クライアントプログラムと、エラーメッセージのコピーを張り付けてあります。 // クラスヘッダーファイル // class Array header #ifndef ARRAY1_H #define ARRAY1_H #include <iostream> using namespace std; class Array { // operator overloading as non-member functions friend ostream &operator<<(ostream &, const Array &); friend istream &operator>>(istream &, Array &); public: Array(int = 10); // constructor with default of 10 elements of array Array(const Array &); //copy constructor ~Array(); // destructor int getSize() const; // size of array // operator overloadings as member functions const Array &operator=(const Array &); // assignment bool operator==(const Array &) const; // check equality of two arrays // because both sides of the operator are constant, // this function must be constant too bool operator!=(const Array &right) const { // fully defined function in the header file like this one // will be made in-line function and save overhead time return !(*this == right); } int &operator[](int); // check subscript range for non-constant array const int &operator[](int) const; // check subscript range for constant array // remember we can only invoke constant function of a constant object // so if we want to check the subscript range of a constant object, we need // to use a constant member function of that object, that's why we need a // constant version of the same functionn as above operator[] private: int size; // size of array int *ptr; // pointer to the first element of the array // so ptr is the name of the array }; // end of class Array definition #endif // 関数定義ファイル // array1.cpp // member function definitions of class Array #include "stdafx.h" #include <iostream> #include <iomanip> using namespace std; using std::cout; #include <new> // for new and delete #include <cstdlib> // for exit() using std::exit; #include "array1.h" // >> , << 以外のオーバーロード関数は省略します // input operator overloading istream &Array::operator>>(istream &input, Array &a) { for (int i = 0; i < a.size; i++) input >> a.ptr[i]; return input; } // output operator overloading ostream &Array::operator<<(ostream &output, const Array &a) { int i; for (i = 0; i < a.size; i++) { output << setw(12) << a.ptr[i]; if ((i + 1) % 4 == 0) output << endl; } if (i % 4 != 0) output << endl; return output; } // クライアントプログラム // ConsoleApplication87.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" #include <iostream> using namespace std; #include "array1.h" int main() { Array integers1(7); // 7 elements array Array integers2; // default 10 element array cout << "size of array integer1 is " << integers1.getSize() << endl; cout << "contents of integers1 after instantiation are :\n"; cout << integers1; cout << "---------------------------------------------\n"; cout << "size of array integers2 is " << integers2.getSize() << endl; cout << "contents of integers2 after instantiation are :\n"; cout << integers2; cout << "---------------------------------------------\n"; return 0; } // エラーメッセージ 1>------ ビルド開始: プロジェクト:ConsoleApplication87, 構成:Debug Win32 ------ 1> array1.cpp 1>c:\users\shiro\documents\visual studio 2015\projects\consoleapplication87\consoleapplication87\array1.cpp(96): error C2039: '>>': 'Array' のメンバーではありません。 1> c:\users\shiro\documents\visual studio 2015\projects\consoleapplication87\consoleapplication87\array1.h(9): note: 'Array' の宣言を確認してください 1>c:\users\shiro\documents\visual studio 2015\projects\consoleapplication87\consoleapplication87\array1.cpp(104): error C2039: '<<': 'Array' のメンバーではありません。 1> c:\users\shiro\documents\visual studio 2015\projects\consoleapplication87\consoleapplication87\array1.h(9): note: 'Array' の宣言を確認してください ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

  • テンプレートクラスのフレンド関数の宣言

    テンプレートクラスに対して、operator << を定義しようとしてハマってしまったので。 ---- 最終的にできたコードはこんな感じ ---- template<size_t M> class MyContainer; template<size_t N> std::ostream& operator<<( std::ostream& os, MyContainer<N> const& cont ); template<size_t M> class MyContainer {  friend   ostream& operator<< <M>( ostream& , MyContainer<M> const& ); <= ここで「operator<<」としてハマった  public:   MyContainer() { }  private:   void Print_( std::ostream& os ) const {    copy( content_, content_ + M, ostream_iterator<int>( os, "\n" ) );   }  private:   int content_[M]; }; template<size_t N> ostream& operator <<( ostream& os, MyContainer<N> const& cont ) {  cont.Print_( os );  return os; } ------------------------------ テンプレートクラスのfriend関数を宣言する場合に、関数に明示的にテンプレート引数を与えないとテンプレート関数の特殊化だけが friend となるようです。 そういうもんだと言ってしまえばそれまでですが、何故こんな変態的な仕様になってるんでしょう? 特殊化された関数だけをテンプレートクラスのfriend に指定したいような状況が想像できません。

  • オーバーライドされた演算子の継承

    オーバーライドされた演算子は継承されますか? 今やろうとしていることは、変換演算子を継承しようとしています。 試してみたところ警告もなく出来ましたが、この動作は規格上正しいのでしょうか? #include <iostream> class base { public: operator bool() { return true; } }; class derived : public base { }; int main() { derived d; if(d) { std::cout << "true"; } }

  • テンプレートクラス中のフレンドクラス

    下記をg++(fedora core1)でコンパイルしたところ、 #include <iostream> using namespace std; template< typename T > class A {   T a; public:   A(T aa ) : a(aa) { }   friend ostream& operator<<( ostream &os, const A &a ); //9行目 }; template< typename T > ostream& operator<<( ostream &os, const A<T> &a ) { return os << a.a; } int main( ) {   A<int>  a(5);   cout << a << '\n';   return 0; } 9行目にこのような警告・エラーが出てコンパイルできませんでした。(下記のオプションも試してみましたがダメでした) friend declaration 'std::ostream& operator<<(std::ostream&, const A<T>&)' declares a non-template function (if this is not what you intended, make sure the function template has already been declared and add<> after the function name here) -Wno-non-template-friend disables this warning. :undefined reference to 'operator<<(std::basic_ostream <char, std::char_traits<char> >&, A<int> const&)' なぜ、コンパイルできないのかが分かりません。ちなみに、bcc32(borland c++ compiler5.5.1)では同様のエラーが出てコンパイルできず、cl(VC++6.0)ではコンパイル・実行可能でした。 ご存知の方いらっしゃったらご教授お願いします。(bccとclはWinXPです)

  • 挿入演算子<<をオーバーロードについて

    はじめまして。 質問があります。 class Foo { ・・・ // NG friend ostream& operator<< (const ostream& out , Foo& c); ・・・ }; 挿入演算子<<をオーバーロードするとき、挿入演算子関数の第1引数をconst ostream& outのようにconstを修飾するとコンパイルエラーに なります。私としては、outの状態を変更したくないという意味 で修飾したのですが、なぜコンパイルエラーになるのかがわかりません。どうかご教授お願いします。 現在、Visual C++ 2005 Express Editionを使用しています。

  • 関数の多重定義(同一タイプの「リファレンス」「値渡し」)

    目黒@C++学習中 です。 下記のソースの実行結果が c:\c++oo\pointline\clspoint.h(27) : 値渡し   P(7,7) c:\c++oo\pointline\clspoint.h(27) : 値渡し   P(7,7) となります。 同一タイプの「リファレンス」と「値渡し」の 多重定義は可能なのでしょうか? それとも、もっと基本的な間違え? [環境]NT4 VC6.0(SP3) #include "clsPoint.h" int main() { Point oP1(2,5); Point oP2(5,2); Point oP3; Point& opP1 = oP1; Point& opP2 = oP2; oP3 = opP1 + opP2; oP3 = oP1 + oP2; cout << oP3 << endl; return 0; } #include <float.h> #include <crtdbg.h> typedef const double cdouble; class Point; typedef const Point cPoint; cdouble dNULL = DBL_MAX; class Point { private: double m_dX; double m_dY; public: Point() : m_dX(dNULL), m_dY(dNULL){}; Point(cdouble dX, cdouble dY) : m_dX(dX), m_dY(dY){}; public: Point operator + (cPoint& oP2) { _RPTF2(_CRT_WARN,"リファレンスP(%g,%g)\n",m_dX+oP2.m_dX , m_dY+oP2.m_dY); return Point(m_dX+oP2.m_dX , m_dY+oP2.m_dY); } Point operator + (cPoint oP2) { _RPTF2(_CRT_WARN,"値渡し   P(%g,%g)\n",m_dX+oP2.m_dX , m_dY+oP2.m_dY); return Point(m_dX+oP2.m_dX , m_dY+oP2.m_dY); } };

  • 演算子オーバーロードのプログラムで

    今、C++でテンプレートクラスや演算子オーバーロードを使ったプログラムの練習をしているのですが、どうしてもうまく動かなく質問させてもらうことにしました。 大まかに言えば、int型のvalueを持ったDataというクラスを用意し、演算子+と-のオーバーロードによって、クラスの足し算引き算を可能にしよう。ということなのですが、 それぞれのオーバーロードした演算子ともに、addSubtractという+と-両方に対応した関数を呼ぶことで使おうと思っています。 コードは以下のようになっています。 1 #include <iostream> 2 3 using namespace std; 4 5 template<class Comparable> 6 class Data { 7  public: 8   Data(){value = 0;} 9   Data(int i){value = i;} 10   int value; 11   Data<Comparable> operator+(const Data<Comparable> &); 12   Data<Comparable> operator-(const Data<Comparable> &); 13   Data<Comparable> Data<Comparable>::addSubtract(const Data<Comparable> & rhs, int sign); 14 }; 15 16 template<class Comparable> 17 Data<Comparable> Data<Comparable>::addSubtract(const 18 Data<Comparable> & rhs, int sign) { 18   int value1=this->value; 19   int value2=rhs.value; 20   Data<int> result(value1+(sign*value2)); 21   return result; 22 } 23 24 template<class Comparable > 25 Data<Comparable> Data<Comparable>::operator+(const Data<Comparable> & rhs) { 26   return addSubtract(&rhs, 1); 27 } 28 29 template<class Comparable > 30 Data<Comparable> Data<Comparable>::operator-(const 31 Data<Comparable> & rhs) { 31   return addSubtract(&rhs, -1); 32 } 33 34 int main() { 35   Data<int> matrix1(2); 36   Data<int> matrix2(1); 37   cout<<"data1:"<<matrix1.value<<endl; 38   cout<<"data2:"<<matrix2.value<<endl; 39 40   Data<int> result1 = matrix1+matrix2; 41   cout<<"data1+data2"<<result1.value<<endl; 42 43   Data<int> result = matrix1-matrix2; 44   cout<<"data1-data2"<<result2.value<<endl; 45 } このコードを実行したところ、以下のようなエラーメッセージが表示されて動かすことができません。 add.cpp:41: instantiated from here add.cpp:26: error: invalid conversion from `const Data<int>*' to `int' add.cpp:26: error: initializing argument 1 of Data<Comparable>::Data(int) [with Comparable = int]' アドバイスをいただけるとありがたいです。

  • C++について。

    現在”猫でもわかるプログラミング”のC++編をSDKと共に勉強している身です。 現在第22章、第23章を勉強中です。 22章 http://www.kumei.ne.jp/c_lang/cpp/cpp_22.htm 23章 http://www.kumei.ne.jp/c_lang/cpp/cpp_23.htm 作業環境はVisual Studio 2005.net C++です 22章でのプログラムを作成し、実行した結果エラーが出てしまいました。 ソースです #include <iostream> class xy_position { int x; int y; public: xy_position(int x = 0, int y = 0){ xy_position::x = x; xy_position::y = y; } int X() const {return x;} int Y() const {return y;} }; ostream& operator << (ostream& o, const xy_position& p) { return o << "(" << p.X() << "," << p.Y() << ")"; } int main(void) { xy_position a(50, 60), b; std::cout << a << b << std::endl; return 0; } (17):error C2143: 構文エラー : ';' が '&' の前にありません。 (17):error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません (17):error C2065: 'o' : 定義されていない識別子です。 (17):error C2059: 構文エラー : 'const' (18):error C2143: 構文エラー : ';' が '{' の前にありません。 (18):error C2447: '{' : 対応する関数ヘッダーがありません (旧形式の仮引数リスト?) (26):error C2679: 二項演算子 '<<' : 型 'xy_position' の右オペランドを扱う演算子が見つかりません (または変換できません)。 このようなエラーが出てしまいました。 もちろんソースは全て同様に書いています。 この”猫でも”で使用しているコンパイラと異なるために出たエラーでしょうか? それに単に cout << のように記述するとエラーが出てしまい、 std::cout << のように記述しなければ通りません。 また、エラーとは別の質問になってしまいますが、プログラム中に int X() const {return x;} という記述がありますが、このconstの意味が分かりません。 単純に return x が変更不可能という意味でしょうか? 次に23章についての質問です。 ここでもソースは同じなのに以下のようなエラーが出てしまいます。 ソースです。 #include <iostream> int main(void) { int x=10, y=15, z=20; std::cout << "16進表示" << std::endl; std::cout.setf(ios::hex); std::cout << x << std::endl; std::cout << y << std::endl; std::cout << z << std::endl; std::cout.unsetf(iostream::hex); std::cout << "8進数" << std::endl; std::cout.setf(ios::oct); std::cout << x << std::endl; std::cout << y << std::endl; std::cout << z << std::endl; return 0; } (8):error C2653: 'ios' : 識別子がクラス名でも名前空間名でもありません。 (8):error C2065: 'hex' : 定義されていない識別子です。 (13):error C2653: 'iostream' : 識別子がクラス名でも名前空間名でもありません。 (15):error C2653: 'ios' : 識別子がクラス名でも名前空間名でもありません。 (15):error C2065: 'oct' : 定義されていない識別子です。 これも何か設定をしなければいけないのでしょうか? なにぶんC++は・・・というかオブジェクト指向の言語は初心者なもので疑問も多いですorz