• 締切済み

global operatorについて

特定のクラスのポインタの比較(less)をオーバーライドしたいのですが、 1. そのような処理は実装可能か? 2. 実装可能とした場合、operatorの宣言は どのように書いたらよいのか? 具体的には以下のようなコードになります。 ---- class Test { public: float m_Priority; Test(const float p) { m_Priority = p; } }; Test* a = new Test(0); Test* b = new Test(1); if(a < b){ a = a; } ---- 試しに bool operator < (const Test* const l, const Test* const r) { return l->m_Priority < r->m_Priority; } と書いてみましたが、コンパイルエラーが出てしまいました。 補足 ・ポインタのオーバーライドが非常に危険なこと ・組み込み方のオーバーライドが禁止されている 上記の2点は確認済みです。 ポインタを格納するクラスを別途作成し、 その中で比較をすればよいのでしょうが、 高速化のためにどうしてもポインタ比較の オーバーライドが必要になりました。

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「ポインタを格納するクラスを別途作成する」のは, 十分実用だと思うけどなぁ. 速度に関しては, コンパイラに依存するけどインラインにすれば問題ないはず. もしくは, 文面で < とは書けないけど関数オブジェクト (+インライン) を使うくらいかな.

回答No.1

bool operator < (const Test& l, const Test& r) { return l.m_Priority < r.m_Priority; } Test* a = new Test(0); Test* b = new Test(1); if(*a < *b) (以下略) でコンパイルできます。

関連するQ&A

  • C++言語 メンバ関数

    何気なく使用しているクラスのメンバ関数、これの中身が実際どうなってるか知りたいです。大別して2種類に分かれますので以下の2つを 教えて下さい。また詳しく載っているサイトなどあれば教えて下さい。 1,stringクラスMid(int start,int length関数と operator関数+について class String{ char *p; char *q; public: //各定義 }; String String::Mid(int start,int length) const { // } String String::operator+(const String&s)const{ return String(p+s.q+s.p); } 最初の方はイメージもつかず、2つめのほうはポインタに ポインタを加えようとしましたとでます。 教えて下さい。

  • operator=()のオーバーロード。

    C++で簡単な多次元ベクトルを扱うクラスをつくっているのですが、 operator=()の実装で躓いてしまいました。 過去ログでは void operator=(CHoge& hoge){ (略) } という実装のアドバイスを見つけられたのですが、 これではa = b = c;といったような代入ができません。 結局*thisを返すように実装しているのですが、うまくいかない原因がどうしてもうまくいかないので、どなたか教えていただけないでしょうか? --------------------------- Windows XP SP2 Microsoft Visual Studio.net theSpokePremium version --------------------------- class vector{ public: /* (中略) */ vector(int dimensions) : d(dimensions) { v = new double[d]; for(int i = 0; i < d; i++){ v[i] = 0.0; } } /* (中略) */ void set(int dimension, double x) { v[dimension] = x; } int size() { return d; } /* (中略) */ vector operator=(vector& right) { if(right.d != d) return INVALID_VECTOR; for(int i = 0; i < d; i++){ v[i] = right.v[i]; } return *this; } /* (中略) */ private: int d; // ベクトルの次元 double *v;// 各成分 } --------------------------- int main() { vector a(3); // a(0.0, 0.0, 0.0) a.set(0, 1.0); // a(1.0, 0.0, 0.0) vector b(3); // b(0.0, 0.0, 0.0) b.set(1, 2.0); // b(0.0, 2.0, 0.0) b = a; for(int i = 0; i < b.size(); i++){ printf("%f ", b.get(i)); } printf("\n"); return 0; } ---------------------------

  • 一時オブジェクト?の生存期間

    CTestというクラスがあって そのクラスにはCTest(const char* a)というコンストラクタがあり bool operator==( const CTest& a )演算子を定義していた場合の話ですが CTest test; bool b = test == CTest("aaa"); このような記述は問題ないのでしょうか? CTest("aaa")は生成されてすぐ廃棄されるかと思いますが この CTest("aaa")の生存期間を知りたいのです。 VC8では問題なく CTest(const char* a) → bool operator==( const CTest& a ) → CTest("aaa");のデストラクタ という順で実行されたのですが、 この場合のCTest("aaa")のデストラクタがいつ呼ばれるかというのはC++の規格で決まっているのでしょうか? C++の初歩的な事かもしれませんが 宜しくお願いします。

  • 多態性を利用して派生クラスの関数を呼びたい

    環境はVS2013,言語はC++です. 基底クラス側で,基底クラスのポインタを引数に受ける仮想関数を宣言し, 派生クラスでその実装をします. 派生クラス側で引数に派生クラスのポインタを受けて,派生クラスのメンバにアクセスできるようにしたいのです. 作成したサンプルを下記に示します. Hello()は関係ありません. また,これはあくまで簡略化したサンプルなだけなので,thisポインタからメンバにアクセスすればよいというものではありません. #include <iostream> class Base { public: int i; Base() :i(0) {} virtual void print(Base *p) { std::cerr << "Base : " << i << std::endl; } virtual void hello() = 0; }; class Super : public Base { public: int x; Super() : x(1) {} void print(Super *p) { std::cerr << "Super : " << p->x << std::endl; } void hello() { std::cerr << "hello" << std::endl; } }; int main(void) { Base *p; p = new Super; p->print(p); } 上記を実行した結果,Base::print()が呼び出されました. print関数の引数に派生クラスSuperの実態を差すBase型ポインタを与えたときに,Super::print()を呼び出せるようにするには,何か方法はありますか. p->print(p)の呼び出し部分をp->((Super*)p)にキャストしても結果は同じくBase::print()が呼ばれました. Base::print()の実装を無くした場合は,未解決の外部参照のコンパイルエラーが発生し, Base::print()を純粋仮想関数にした場合は,Super側でSuper::pirnt(Base*p)を実装しなければならないのか,抽象クラスのインスタンス化ができないというコンパイルエラーが発生します. これは,派生クラスとはいえ,引数リストの型が違うのでオーバーライドされていないということですよね. 引数をBase *p,Super *pからそれぞれvoid *pへ変更し,Super::print()内で(Super *)へキャストしなおしたところ,きちんとオーバーライドされ,うまくはいきました. しかしながら,この方法だと派生クラス側で実装する際に毎回キャスト処理を書かなくてはなりません. 他に何かきれいな方法はないでしょうか.

  • オブジェクト指向で、インターフェースにないメソッドを呼ぶ

    こんにちは。質問させてください。 現在C++でプログラムを書いているのですが、以下のようなプログラムを書いたとします(これ例ですので、実際のプログラムとは異なります)。 // ポインターを抽象化 class PointerInterface { }; // 抽象化したクラスを継承して整数型のポインタを作る class IntPointer : public PointerInterface { private:   // int型のポインタ   int *p; public:   int* get()   {     return p;   } }; // 抽象化したクラスを継承して少数型のポインタを作る class FloatPointer : public PointerInterface { private:   float *p; public:   float* get()   {     return p;   } }; PointerInterface* CreateInterface( bool flag ) {   PointerInterface* result = 0;   if( flag )   {     result = new IntPointer;   }   else   {     result = new FloatPointer;   }   return result; } void setIntPointer( PointerInterface* ptr ) {   // ここでint型のポインターを取り出して操作したい } void main() {   PointerInterface* ptr = CreateInterface( true );   setPointer( ptr ); } インターフェースは同じなのに継承先に内含されている変数のタイプが違い、それを取得したい場合が出てくると思います。 こういう場合どのように実装すれば、より美しくコーディングすることができるでしょうか? /* 私は 1:PointerInterfaceにvoid*を戻すメソッドを宣言する 2:setIntPointerの中で無理やりキャストして子クラスのgetを無理やり呼び出す という2つの方法が思いついたのですが、なんだかどっちのコーディングもピンときません。 お知恵を貸してください! ※今回はtemplateを使うというのは、なしでお願いします。 */

  • C++の問題で・・

    C++の問題で・・ 参考書に「簡易的な文字列クラスStringを作成せよ。」という問題があり作りました。 いかにそのコードを示します。今回の質問の内容に関係ないとおもうところや、インクルードなどは省かせていただきます。 環境は Visual studio 2008です。OSはXPです。 class String{     int len; //文字列の長さ     char *s; //文字列の先頭文字へのポインタ public:     String(const char *);     int length()const{return len;} //長さを求める     operator const char * ()const{return s;}     bool operator==(String &a)const{return strcmp(this->s, a);}     char *operator+(String&)const; }; char * String::operator +(String &a)const {     char *memory = new char[this->len + a.len + 1];     memory[0] = '\0';     return strcat(strcat(memory, this->s), a); } String::String(const char *p): s(const_cast<char *>(p)), len(strlen(p)){} String::String(const String &x) {     s = x.s;     len = x.len; } inline std::ostream& operator<<(std::ostream &s, String &x) {     return s << static_cast<const char *>(x); } int main() {     String a("My name is Paul");     String b("My name is Paul");     String c("My name");     String d(" is Paul");     cout << "a = " << a << "\n";     cout << "b = " << b << "\n";     cout << "c = " << c << "\n";     cout << "d = " << d << "\n";     cout << "a == b " << (a == b) << "\n";     cout << "a == c " << (a == c) << "\n";     cout << "c + d = " << (c + d) << "\n"; }     このようなプログラムなのですが、上記の char * String::operator +(String &a)const {     char *memory = new char[this->len + a.len + 1];     memory[0] = '\0';     return strcat(strcat(memory, this->s), a); } ところで、 memory[0] = '\0'; を除くと文字列を出力した結果をみると、先頭にいらない言葉が入っています。 僕の場合は x9My name is Paul と表示されます。文字化け・・ではないのですが、ゴミのようなものが・・ どうしてこのようなことが起こるか、どこでゴミが入ってしまうのか教えてほしいです。 稚拙なプログラムで申し訳ないです。 もし、間違っている場所や、もっと簡単にかけるようなところがあれば、ご指摘いただくとありがたいです。 よろしくお願いします!

  • template 参照 operator について

    「ゲームプログラマになる前に覚えておきたい技術」という書籍を読みながらC++でプログラミングの学習をしているのですが、template class と 参照 と operator の組み合わさったクラスでわからないところがあります。 自分で出来る限り調べてみましたが、解決できなかったので、答えていただけると幸いです。 Cの学習はひととおり済んでおりますが、まだC++は学習を始めたばかりなので理解が浅いです。 質問内容にいたらない点があるとは思いますが、お願いします。 以下のようなクラス定義文がありました。 template< class T > class Array2D{ public: Array2D() : mArray( 0 ){} ~Array2D(){ delete[] mArray; mArray = 0; } void setSize( int size0, int size1 ){ mSize0 = size0; mSize1 = size1; mArray = new T[ size0 * size1 ]; } T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } const T& operator()( int index0, int index1 ) const { return mArray[ index1 * mSize0 + index0 ]; } private: T* mArray; int mSize0; int mSize1; }; この定義文の以下の部分 T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } において、T&という記述がなければ、()という演算子のはたらきを再定義していて、 mArrayを2次元的に利用できるように値を返しているように見えるのですが、 T&がつくことによって、なにがどうなっているのでしょうか。 それと、参照というのは、利用するときには必ず初期化が必要、と学習したのですが、 この場合、初期化の処理になっているのでしょうか。 今までに出てきた参照では、簡単な例でいうと int n; int& m = n; というように、型名&別名=参照先 と、即初期化して使っていました。 これなら初期化されているのはわかりますが、今回のように、 「別名」の部分がoperatorになっていると、どのアドレスが「別名」が指すアドレスになるのでしょうか。 さっぱりわかりません。 質問の連続になってしまって申し訳ありません。 ほんとに困ってます。 おねがいします。

  • C言語 strstrの実装

    課題で strstr()と同じ働きをするmy_strstr()を実装しなさいという課題がでています。 strstr()は char *strstr(const char *s1, const char *s2) という形で、 文字列s2が文字列s1の中に含まれていれば、文字列1の文字列2が含まれている先頭のアドレス(ポインタ)を返す関数です。(すいません、説明が下手で) 例えば、 strstr(Japanese, pan)は Japanese にpan が 含まれるのでpan 以降の文字列を返します→panese *********************** 質問ですが、 strstrの実装は完成して、正常に動くのですが 警告がでてきます。 str1= Japanese str2 = pan とすると、 私のプログラムでは、次のようなプロセスで動きます。 一文字ずつ調べる ↓ str1のJと str2の pを比較        J != p → str1++; //str1の次の文字へ str1のaと str2の pを比較        a != p, str1++; //str1の次の文字へ str1のpと str2の pを比較        p == p, rec = str1 // str1のアドレスを記録         str1++; str2++; //次の文字へ str1のaと str2の aを比較        a == a, str1++; str2++; //次の文字へ str1のnと str2の nを比較        n == n, str1++; str2++; //次の文字へ str1のeと str2 nullを比較    *str2 = null //search 終了。 return rec; とこんな感じです。 このプロセスの3行目の rec = str1; つまり、関数の戻り値のために記録したstr1のところで、 「問題のあるポインタ変換」 という警告がでます。 これは s1がconstだからでしょうか? どのようにしたらこの警告が消えるでしょうか? どなたかよろしければアドバイスをいただけませんか。 お願いします。

  • 仮想基底クラスをもつクラスの代入演算2

    <仮想基底クラスをもつクラスの代入演算>の続きですが、結局、assign のようなものを作って、以下のように書くのが一番いいのでしょうか。。。 ====(一応、自己代入も考慮して書くと^^) #include <algorithm> struct X { int x; X &assign(const X &z, bool top) { if (this != &z) x = z.x; return *this; } X &operator=(const X &z) { return assign(z, true); } }; struct A : virtual X { int a; A &assign(const A &z, bool top) { if (this != &z) { if (top) X::assign(z, false); a = z.a; } return *this; } A &operator=(const A &z) { return assign(z, true); } }; struct B : virtual X { int b; B &assign(const B &z, bool top) { if (this != &z) { if (top) X::assign(z, false); b = z.b; } return *this; } B &operator=(const B &z) { return assign(z, true); } }; struct C : A, B { int c; C &assign(const C &z, bool top) { if (this != &z) { if (top) X::assign(z, false); A::assign(z, false); B::assign(z, false); c = z.c; } return *this; } C &operator=(const C &z) { return assign(z, true); } }; ==== ただ、<仮想基底クラスをもつクラスの代入演算>で、jacta さんが提示してくださった方法も、処理量は増えますが、アロケートする必要があるポインタなどのデータメンバのアロケートやデリートする処理コードをコンストラクタに集中できるので、「コーディング量の減少・改変の際の修正し忘れの可能性を低くできる」というメリットがあると思います。ハンドルクラスやコンテナクラスを実装する際は、swap() 機能が必要となると考えられるので、jacta さんのコピーコンストラクタでコピー代入を実装する方法の方がいいのかとも思います。 みなさん、どう思われますか? また、そのほかに、効果的なテクニックがあれば、ぜひ、ご教示ください。

  • std::lower_boundについて

    こんにちは。 std::vector< int* > IntArray; IntArray.push_back( new int( 0 ) ); IntArray.push_back( new int( 2 ) ); IntArray.push_back( new int( 1 ) ); IntArray.push_back( new int( 6 ) ); IntArray.push_back( new int( 5 ) ); IntArray.push_back( new int( 7 ) ); というint型のポインタが格納されているIntArrayを bool cmp( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::sort( IntArray.begin(), IntArray.end(), cmp ); として並べ替えたとします。 そこで新しく new int( 4 )をソートされた順番を壊さない位置に挿入したいと思いlower_boundを使用しようと思いました。 しかし、lower_boundの使い方がいまいちわかりません。 int *p = new int( 4 ); bool cmp2( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::lower_bound(  IntArray.begin(),  IntArray.end(),  p,  cmp2 ); 上記のように使用すればこの場合だと変数pを挿入する位置が返ってくるのでしょうか? 間違えているとしたら、どのように修正すれば変数pを挿入できる位置が返ってくるように書き直すことができるでしょうか?(むしろそういった実装は可能なのでしょうか) よろしくお願いします。 今回は特殊ケースでの問題ですのでint* pをintに修正する、挿入してから再度ソートする、といったことはなしでお願いします。あくまでもlower_boundで実装する場合のコードについてでよろしくお願いします。 /*   VisualStudio 2008 academic edition   Window7 64bit */