operator * の使用方法と挙動についての質問

このQ&Aのポイント
  • 質問1:関数内での(*this)[idx]の使用でコピーが作成されるかどうかについて疑問があります。
  • 質問2:CTestクラスのoperator * が呼び出されない理由について教えてください。
回答を見る
  • ベストアンサー

operator * について

掛け算ではない方の operator * についての質問です。 下のソースを見てください。関数func()内で、(*this)[idx]というやり方と、直接operator [] を呼び出すやり方を試しています。(*this)[idx]は自分のコピーを作ってしまわないでしょうか?このようなやり方は正しいでしょうか。というのが第1の質問です。 さらに、CTestで operator * を定義していますが、(*this)[idx]で呼び出されません。なぜなのでしょうか。というのが第2の質問です。 どうぞよろしくお願いいたします。 class CTest : public vector<int> { public: CTest() : vector<int>() { push_back(1); push_back(2); push_back(3); } void func() { #if 1 // 質問1 この書き方をしてもコピーが作られないかどうか? cout<<(*this)[0]<<endl; cout<<(*this)[1]<<endl; cout<<(*this)[2]<<endl; #else cout<<operator[](0)<<endl; cout<<operator[](1)<<endl; cout<<operator[](2)<<endl; #endif } CTest& operator * () { // 質問2 なぜこのオペレータが呼び出されないのか cout<<"???"<<endl; return *this; } }; void main(void) { CTest inst; inst.func(); }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

解答1:  作られません。*thisは参照扱いなので、コピーされることなく std::vectorの配列オペレータを実行しますので、大丈夫です。  どうしても心配であれば   CTest &ctest = *this;   cout<<ctest[0]<<endl;  と参照型に代入してから実行してみるといいかもしれません。 解答2:  CTestクラス自身に operator[]がないので、基底クラスである std::vectorの operator[]が呼ばれています。  operator *()のメンバ関数は配列アクセスするためのものではありません。  main関数内でただ   *inst;  という一文を実行してみてください。これで operator *()が呼ばれます。  配列アクセスしたいのであればオペレータは例えば以下のように定義してしてみてください。   int operator [](int index)  尚、*が付いた operatorで配列アクセスみたいなことをさせたい場合、  例えば   class Hoge   {   public:     enum { array_size = 5 };     Hoge()     {       for(int i=0; i<array_size; ++i)  t[i] = i;     }     operator int* ()  { return this->t; }        int    t[array_size];   };  のようなクラスに operator <type>*という形のオペレータを用意すれば   Hoge a;   for(int i=0; i<Hoge::array_size; ++i)     std::cout << a[i] << " ";   std::cout << std::endl; のように使用できます。  が、今回の Ctestクラスで使うことはできないでしょう。  コンパイラが基底クラスの配列オペレータと上記のオペレータのどちらを使えばいいのか判断できないからです。

honehone51
質問者

お礼

ありがとうございます。大変参考になりました。 質問1について この場合、コピーが作られないということが理解できました。(*this)と書いていいことはわかったので、そうします。ところで、*this が参照扱いというのは、言語的にそういうことになっているのでしょうか。もしご存知でしたら、教えていただけるとさらに助かります。 質問2について 私は operator * () の意味を、 CTest *pinst = new CTest; CTest clone = *pinst; とした時の2行目のコピーの部分で呼び出されるものと思っていました。しかし、試してみるとこの場合呼び出されず、教えていただいた *inst; とした時呼び出されました。質問1の所に書いたこととかぶりますが、つまり、ポインタから実体への参照に型変換するオペレータ * はオーバライドできず、参照渡しされることがどこかで決まっていて、コンパイラがそういう風なコードを作ることになっていると考えていいでしょうか。 operator int* () の例、勉強になりました。ありがとうございました。

その他の回答 (1)

回答No.2

 No1です。 > ところで、*this が参照扱いというのは、言語的にそういうことになっているのでしょうか。  *thisで使われている単項演算子 *は間接参照を行い、T*型を T型の左辺値に変換します。  なので、型としの参照というわけではありません。 > ポインタから実体への参照に型変換するオペレータ * はオーバライドできず、  はい、できません。

honehone51
質問者

お礼

本当にありがとうございます。自分の疑問を解決することができました。ありがとうございました。

関連するQ&A

  • vectorを引数とする関数

    以下のようなプログラムにおいて、 #include <stdio.h> #include <cstdlib> #include <iostream> #include <vector> #include <fstream> #include <sstream> #include <map> using namespace std; double func(std::vector<double> *tmp2); int main(){ vector <double> tmp; tmp.resize(0); tmp.push_back(0.12458); tmp.push_back(-12.45); tmp.push_back(4.253); cout << func(&tmp) << endl; return 0; } double func(std::vector<double> *tmp2){ return tmp2[1]; } vector tmpをfuncに渡して、tmp[1]、すなわち、 -12.45が出力されるようにしたいと思います。 ですが、どうしてもコンパイルエラーが残ります。 どのようにすればよいでしょうか?

  • c++のvector::erase

    vector::eraseについて質問させてください。 vector::eraseでググるとforループ内でのeraseの仕方は 書いていあるのですが、単純に1要素だけeraseする 例が見当たらなかったので教えてください。 1要素を削除する場合、 以下のような書き方でよろしいのでしょうか? いちおう正しく動作しているようです。 ただ、疑問なのは途中の要素[2]を削除しているので、 後半の要素が詰め直されているのか、 そのあたりが自信がなくて不安です。 vector<string> v; v.push_back("0a"); v.push_back("1a"); v.push_back("2a"); v.push_back("3a"); v.push_back("4a"); v.erase( v.begin() + 2 );//v[2]を削除 //結果表示 for(unsigned int i=0; i<v.size(); i++){ cout<<v[i]<<"\n"; } cout<<endl;

  • operatorは、派生で使用できない?

     以下のような例では、エラーとなります。 よい案がありましたら、教えてくださいませ class CManiac { private: int m_iValue; public: int GetiValue() { return m_iValue; } CManiac& operator=(int iValue) { m_iValue = iValue; return *this; } }; class Ctest public CManiac { } main() { Ctest test; test = (int)123; // error }

  • Cygwinでg++がグローバル関数をはじいてしまう

    現在Win XP上にGygwinを導入し C++の勉強をしています。 書籍を購入し、以下のプログラムを試したところ グローバル関数宣言をしているにもかかわらず main() とfunc1()中で変数”count”が undeclared (first use this function) として弾かれてしまいます。 どうしてなのでしょうか? よろしくお願いします。 //example global variavle. #include<iostream> using namespace std; void func1(); void func2(); static int count; //This is global variavle. int main() { int i; //This is local variavle. for(i=0; i<10 ; i++){ count = i * 2; func1(); //calling func1(). } return 0; } void func1() { cout << "count: " << count; //access global "count" cout << "\n"; func2(); //calling func2(). } void func2() { int count; //define local "count" for(count=0;count<3;count++) { cout << "."; } }

  • 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; } ---------------------------

  • ラムダ式を関数に渡したいのですが

    Class1からClass2にある関数の引数にラムダ式で関数を渡すようなプログラムを作ろうと思い、以下のようにコードを記述しました。 #include <iostream> class Class1 { int i = 0; void func() { std::cout << "Hello world" << std::endl; } void init() { Class2 *class2 = new Class2(); class2->setFunc([this] { func(); i++; }()); } }; class Class2 { void(*mFunc)(); void runFunc(){ mFunc(); } public: void setFunc(void func()) { mFunc = func; } }; すると class2->setFunc([this] { func(); i++; }()); のところで「型"void"の引数は型"void(*)()"のパラメーターと互換性がありません」というエラーが発生してしまいます。 キャプチャにthisを渡したラムダ式を他のクラスの関数ポインタのような変数に代入させるようにしたいのですがどのように記述したらできますか

  • 【C++】関数ポインタの代入

    C++の関数ポインタについて質問です。 下記のように関数ポインタを宣言し、3通りの代入を行ってみました。 (3)のように関数名の頭に&を付けた場合と(2)のように&を付けなかった場合で 全く動きが同じになってしまうのですが、何故なのでしょうか? ------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; void Func1(){ cout<<"Func1が呼ばれました。"<<endl; return; } int main() { //(1) void (*fp1_1)(); fp1_1 = Func1; fp1_1(); //(2) void (*fp1_2)()=Func1; fp1_2(); //(3) void (*fp1_3)()=&Func1; fp1_3(); getchar(); return 0; }

  • 下記、プログラム内の「char *」の役割

    C++初心者です。 縦長になってしまいますが、 『 #include <iostream.h> void show(int); void show(double); void show(char *);   ←左記の記述の使い方 int main(void) { show(1); show(0.25); show("文字列"); return 0; } void show(int x) { cout << x << endl; } void show(double y) { cout << y << endl; } void show(char *z) { cout << z << endl; } 』 のプログラムにおいて、「char *」の使い方がいまいち理解できません。 上記プログラムですとエラーが表示されないのですが、下記のプログラムだとエラーが発生します。 『 #include <iostream.h> void show(int); void show(double); void show(char);   //←---------上記と違う行 int main(void) { show(1); show(0.25); show("文字列"); return 0; } void show(int x) { cout << x << endl; } void show(double y) { cout << y << endl; } void show(char z) {  //←---------上記と違う行 cout << z << endl; } 』 なぜ、ポインタ(*)を付けないといけないのか分かりやすく教えていただけましょうか。

  • POJ 2718

    #include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; int numbers[10]; int length; int n; int permutation(int num[10]){ int i; int oneco=0; for(i=0;i<length;i++){ if(num[i]){oneco++;} } int length2 = length-oneco; if((oneco==length)||(oneco==0)){return 1000000000;} if(abs(length2-oneco)>=2){return 1000000000;} vector<int> one; vector<int> two; for(int i=0;i<length;i++){ if(num[i]){one.push_back(numbers[i]);} else{two.push_back(numbers[i]);} } int len1 = one.size(); int len2 = two.size(); //cout << len1 << len2 << endl; // int num1[10];int num2[10]; vector<int> num1; vector<int> num2; //cout << one[1] << one[2] << endl; int count1=0;int count2 = 0; sort(one.begin(),one.end()); sort(two.begin(),two.end()); do{ int num=0; for(int i=1;i<len1;i++){ int onei = one[i]; for(int i2=0;i2<i;i2++){ onei = onei*10; } num = num + onei; }//cout << num << endl; if(one[0]==0){num = num;} else {num = num + one[0];} num1.push_back(num); //cout << num << endl; count1++; }while(next_permutation(one.begin(),one.end())); do{ int num = 0; for(int i=1;i<len2;i++){ int twoi = two[i]; for(int i2 =0;i2<i;i2++){ twoi = twoi*10; } num = num + twoi; // cout << num << endl; }//cout << "here" << num << endl; if(two[0]==0){num = num;} else {//cout << num ; num = num + two[0]; //cout << " " << num << endl; } num2.push_back(num); //cout << "here" << num << endl; count2++; }while(next_permutation(two.begin(),two.end())); int ans = 1000000000; //cout << len2; int dummy1 = 1; for(int x=1;x<len1;x++){ dummy1 = dummy1*10; }//cout << dummy1; int dummy2 = 1; for(int x=1;x<len2;x++){//cout << dummy2<< endl; dummy2 = (dummy2)*10; //cout << dummy2<< endl; }//cout << dummy2; for(int i=0;i<count1;i++){//cout << num1[i] << dummy1 << endl; if((num1[i]%dummy1)==num1[i]){if(num1[i]!=0){continue;}} for(int i2=0;i2<count2;i2++){ if((num2[i2]%dummy2)==num2[i2]){if(num1[i]!=0){continue;}} ans = min(ans,abs(num1[i]-num2[i2])); } } return ans; } //int permutation(int i[10]){return 1;} int dfs(int i,int num[10]){ if(i==length) return permutation(num); num[i]=0; int ans1 = dfs(i+1,num); num[i]=1; int ans2 = dfs(i+1,num); return min(ans1,ans2); } int main(){ cin >> n; getchar(); for(int i=0;i<n;i++){ /*for(length=0;length<10;length++){ cin >> numbers[length]; char c = getchar(); if(c=='\n'){break;} }*/ string str; while(1){ char c = getchar(); if(c=='\n'){break;} str += c;} length = 0; for(int i2=0;i2<str.length();i2=i2+2){ numbers[length] = (int)str[i2]-'0'; length++; } // cout << length; int dummy[10] = {0,0,0,0,0,0,0,0,0,0}; cout << dfs(1,dummy) << endl; } } 上記のどこが間違っているか教えてください。POJの2718です。書いてあるテストは通りました。

  • 仮想関数でのオーバーライドでの質問

    仮想関数でのオーバーライドでの質問 二つの派生クラスを定義したのですが、一つ目のクラスのメソッドが実行されないで困っています。 下記にソースを載せておきます。 どこが原因でそうなるのかご指摘お願いします。 /* 継承 */ #include <iostream> using namespace std; class Var { private: int value; static Var* re; public: // 静的関数 static bool func() { // 内部で同一の関数を呼び出す re->show(); return true; } virtual show() { cout << "message00" << "moji" << endl; } // 自身のポインタを取得 Var() { re = this; } }; Var* Var::re = NULL; class Msg01 : public Var { private: int value; public: show(void) { cout << "message01" << "moji" << endl; } }; class Msg02 : public Var { private: int value; public: show(void) { cout << "message02" << "moji" << endl; } }; int main() { Msg01 val; Msg02 msva; val.func(); msva.func(); getchar(); return 0; } /------------------------------------------------------/ 実行結果 message02moji message02moji /------------------------------------------------------/ message01mojiが表示されるはずなんですが表示されないでいます。 Msg02を宣言したためこのようになってしまったんでしょうか?

専門家に質問してみよう