• ベストアンサー

C++

以下にソースを提示します。少々長いことをお許しください。 #include <iostream> #include <string> using namespace std; class Aru{ private: int data; public: Aru(int d): data(d){}; int get_data() const { return data; }; }; class Betu{ private: Aru *a; public: Betu(); ~Betu(); Betu (int x); void input(); void show() const; int get_data() const { return a->get_data(); } }; Betu::Betu(int xv):a(0){ a = new Aru(xv); } Betu operator+(Betu& aa, const Betu& bb){ int data = aa.get_data() + bb.get_data(); Betu temp(data); return temp; } Betu::Betu():a(0){} Betu::~Betu(){ delete a; } void Betu::input(){ int d; delete a; cout << "数字を入力してください" << endl; cin >> d; a = new Aru(d); } void Betu::show() const{ if(a==0) return ; cout << "データ:" << get_data() << endl; } int main() { Betu one; Betu two; Betu three; one.input(); two.input(); three = one + two; three.show(); } コンパイルは普通に警告も出ずに通ります。 しかし実行時にエラー・・・・・ まだC++学習のみでエラーを取ることができません。 おそらくoperatorの部分が影響していると思うのですが・・・ ちなみにこのプログラムはoperatorの練習のために作ったプログラムのため、意味のないものになっていますが気にしないでください。 よろしくお願いします。

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

  • ベストアンサー
  • lv4u
  • ベストアンサー率27% (1862/6715)
回答No.3

とりあえず、以下のようにコピー代入演算子を追加して、加算演算子の処理を修正するとOKみたいです。 (環境:C++Builder4) C++の学習は、こんな短いプログラムを作って動作させながら(エラーを出しながら・・)地道に覚えていくのがいいみたいですね。C++って、マスターするのは大変だけど、その見返りは大きい気がするので、久しぶりに私も、勉強する意欲が出てきます。 class Betu{ private: Aru *a; public: Betu(); ~Betu(); Betu (int x); Betu &operator=(Betu be); //*** add **** void input(); void show() const; int get_data() const { return a->get_data(); } }; Betu operator+(Betu& aa, const Betu& bb){ return Betu(aa.get_data() + bb.get_data()); } //<<<*** add ************ Betu &Betu::operator=(Betu be){ delete a; a = new Aru(be.get_data()); return *this; } //>>>*** add ************

noconan
質問者

お礼

返答ありがとうございました。 そして、サンプルソースまで載せていただきありがとうございました。 コピー代入演算子の定義で行ってみたところエラーを取り除くことができました。 エラーの原因はNo1の回答者さんの返答に書いたように、発見できてほっとしています。 現在学生のみですが、学校の授業だと"C++のみ”という授業がありません。C言語ならあるのですがオブジェクト指向は難しいと考えているためでしょうかね?  そのため自分で勉強していく他ないのですが、ある意味では授業で覚えるより個人で何回も練習しているほうが身につくかもしれませんね。かけですけど^^

その他の回答 (3)

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.4

代入演算子は侮れないものがありますね。 例えば lv4u 氏の定義したそれだと ・値渡しで引数を渡しており、しかも使用しているコピーコンストラクタがデフォルトのままなので、問題が発生する可能性がある ・いきなり delete a しているので、new Aru(...) が例外を投げたときに問題が発生する可能性がある となっており、結構大変です。

noconan
質問者

お礼

返答ありがとうございました。 今までC言語を勉強し、SDKも学んでいる身ですが、C++は癖がありますね。koko_u_さんがおっしゃられる通り、一番理解しにくいのがこの代入演算子などオペレータを自分で定義する部分です。 自分はなれるために数多く読み、数多く書くことが大事と考えて記述してきましたが、いまだに直感で「ああ、こうか」という域に達しませんorz 解説はごもっともです。 しかし一応解決の1つの方法として考えられるので、例外処理などはのちのち・・・・・ ありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

クラス Betuがポインタをメンバー変数として持っていて、その(デフォルト)コンストラクタでメモリ割り当てしているのに、 コピーコンストラクタと代入演算子の定義をしていないからじゃないかな。

noconan
質問者

お礼

返答ありがとうございました。 エラーが出た理由は初めに回答してくれた方のおかげで理解することができました。 この解決策はsakusaker7さんがおっしゃる通り、コピーコンストラクタと代入演算子の定義が必要になりますね。 ありがとうございました。

  • arihina
  • ベストアンサー率26% (4/15)
回答No.1

+オペレータの中で定義したBetuクラスのローカルオブジェクトが、+オペレータが返り値を返した段階で破棄されているのではないでしょうか。 したがって、showメソッドの中のget_dataメソッドが失敗しているのではないでしょうか。

noconan
質問者

お礼

返答ありがとうございました。 確かにおっしゃる通りですね・・・ ローカルオブジェクトと値を返したオブジェクトが同じdataをさすことになり、+オペレータが返り値を返した段階でデストラクタが呼ばれローカルオブジェクトは破棄されてしまう。 すると値を返したオブジェクトがdataを参照したとしても、そこにはエラーがないということですね。 ありがとうございました!

関連するQ&A

  • C++ 動的確保について

    学校の演習課題で「クラス Array のメンバ変数を以下のように変更して,配列のサイズを実行時に決められるようにしたい.コンストラクタを適切に修正しなさい.配列のサイズはコンストラクタの引数で指定できるようにすること.main 関数内のオブジェクトの宣言部分を適当に変更して動作を確認しなさい.」という課題が出ました。 指示のメンバ変数の変更は、sizeを定数にしていたものを変数にし、arrayを配列からポインタにする点です。 もとのプログラムはI、私がいじったものがIIです。どうにもセグメンテーションフォルトから抜け出せなくて困っています。どのようにしたら題意のプログラムになるのでしょうか? よろしくお願いします。 ここからI~ #include <iostream> using namespace std; class Array{ private: const static int size = 6; int array[size]; public: Array( ); int getSize( ); void put( int index, int data ); int get( int index ); void show( ); }; Array::Array( ) { for ( int i = 0; i < size; i++ ) { array[i] = 0; } } int Array::getSize( ) { return size; } void Array::put( int index, int data ) { array[index] = data; } int Array::get( int index ) { return array[index]; } void Array::show( ) { cout << "| "; for ( int i = 0; i < getSize( ); i++ ) { cout << get(i) << " | "; } cout << endl; } int main( ) { Array array1; array1.put(1, 2); array1.put(4, 1); array1.show( ); return 0; } ~ここまでI ここからII~ #include <iostream> using namespace std; class Array{ private: int size; int *array; public: Array(int s); ~Array(); int getSize(); void put(int index, int data); int get(int index); void show(); }; Array::Array(int s) { size = s; array = new int; for (int i = 0; i < size; i++) { *array = 0; array++; } array -= size; } Array::~Array() { delete[] array; cout << "デストラクタが呼ばれました。配列の要素数分のメモリを開放します." << endl; } int Array::getSize() { return size; } void Array::put(int index, int data) { *(array + index) = data; } int Array::get(int index) { return *(array + index); } void Array::show() { cout << endl << "| "; for (int i = 0; i < getSize(); i++) { cout << get(i) << " | "; } cout << endl; } int main() { int s = 0; cout << "確保するサイズを入力してください:"; cin >> s; Array array1(s); array1.put(1, 2); array1.put(4, 1); array1.show(); return 0; } ~ここまでII

  • C言語の参照はずしについて

    ソートのプログラムなんですが #include <stdio.h> #include <stdlib.h> int comp(const void *, const void *); int main() { int i; int test[6] = {10, 8, 2, 6, 4, 0}; qsort(test, (size_t)6, sizeof(int), comp); printf("\n"); for (i = 0; i < 6; i++) printf("%d\n", test[i]); return 0; } int comp(const void *a, const void *b) { static int i = 1; printf("%02d--%d,%d\n", i, *(int *)a, *(int *)b); i++; return (*(int *)a - *(int *)b); } 最後のreturnの()の中身がよくわかりません。「参照はずし」という事をしてるらしいんですが「参照はずし」とは何ですか意味も教えてください。

  • メンバ関数にconstをつけた際の問題

    C++を勉強中の学生です。 以下のようなコードで問題が起こりました。 class TEST{ private: int mArray[10]; //(int a;) public: int* get_mArray(void) const; //(int get_a(void) const;) }; int* TEST::get_mArray(void) const{ return mArray;    //配列の先頭要素の値を受け取りたい。 } //(関係のありそうな部分のみを抜き出しました) このコードにおいて、関数は値を変えない事が明白なので、constをつける必要性はないのですが(癖でつけた際に発生した問題です)、 なぜconstをつけると動作しなくなるのか知りたいです。 //()で囲った部分を有効にし、 int TEST::get_a(void) const{return a;}という関数はエラーにならなかったのですが、どのような違いがあるのでしょうか? 出たエラーは(visual C++ 2010) 'const int [10]' から 'int *' に変換できません。 というものでした。 ポインタとconst関連の部分を手持ちの本で勉強しなおしたのですが、解答を得られなかったのでこちらで質問させてもらいます。

  • 下記、プログラム内の「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; } 』 なぜ、ポインタ(*)を付けないといけないのか分かりやすく教えていただけましょうか。

  • 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

  • 今,C++のコンストラクタを勉強しているのですが,これの働きと役割がい

    今,C++のコンストラクタを勉強しているのですが,これの働きと役割がいまいちわかりません class const{ public: int a; const(); } const::const() { a = 100; } int main() { const c; cout << " c.a = " << c.a << endl; return 0; } この様な例がのっていたのですが、[const c;]は何を定義しているのでしょうか, [c.a]はどの変数のことをさしているのでしょうか?教えてください。

  • C言語

    3. 整数配列data の,data[left]からdata[right-1]の最小値がある添字番号を返す関数 int min_ind_ary(const int data[ ], int left, int right) で最小値が複数あるときは,一番小さい添字を返すようにするにはどうしたらよいのかわかりません? 途中経過↓ #include <stdio.h> int min_ind_ary(const int data[10],int left,int right) { int i,min = 0; for( i = 1; i < left; i++){ if(data[min] < data[i]) min = i; } return min; } void print_ary(const int data[10], int size){ int i; for(i = 0; i < 10; i++){ printf("%2d", data[i]); } } void sort_ary (int data[10], int size) { int i; for(i = 0; i < size - 1; i ++ ) { int min, work; min = min_ind_ary(data, i, size); work = data[min]; data[min] = data[i]; data[i] = work; } return; } int main(void) { int data[10] = {1, 6, 4, 8, 2, 3, 5, 9, 7, 4}; print_ary(data, 10); sort_ary(data, 10); print_ary(data, 10); return 0; }

  • C言語

    C言語の問題が分からなくて困ってます。 時間がないのでわかる方教えていただけますでしょうか。次の1️⃣2️⃣3️⃣です。 整数割り算の結果と余りを同時に求める関数 div_mod_intを作成せよ。 ただし、ゼロ割り算は考慮しなくて良い。 * 整数割り算の結果と余りを同時に求める関数を作成 #include <stdio.h> int input_int(int *pd); void div_mod_int(int data1, int data2, ____1⃣____); int main(void) { int data1, data2; int syou, amari; while (input_int(&data1) != EOF && input_int(&data2) !=EOF) { div_mod_int(data1, data2, ____2⃣____); printf("%d / %d = %d...%d\n\n", data1, data2, syou, amari); } return 0; } /* * 整数割り算を行い商と余りを求める * 引数 int data1 :被除数 (割られる数) * int data2 : 除数 (割る数) * int data1 / data2 : 除算結果 * int data1 % data2 : 余り * 戻り値 void :なし */ void div_mod_int(int data1, int data2,____1⃣____) { ____3⃣____ __________ }

  • c言語の関数について

    .#include<stdio.h> int input_number(void); int main(void) { int num; int total = 0; while(){ num = input_number(); if(num == 0){ break; } total = total + input_number(); } printf("¥n合計値は%dです¥n", total); return 0; } int input_number(void) { int num; printf("数値を入力してください: "); scanf("%d", &num); return num; } 個人でcを勉強しております。 このプログラムで間違っているところを教えていただけませんでしょうか? 苦戦して困っております。できれば勉強法も教えてていただきたいです。 どうか宜しくお願いします。

  • 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 と表示されます。文字化け・・ではないのですが、ゴミのようなものが・・ どうしてこのようなことが起こるか、どこでゴミが入ってしまうのか教えてほしいです。 稚拙なプログラムで申し訳ないです。 もし、間違っている場所や、もっと簡単にかけるようなところがあれば、ご指摘いただくとありがたいです。 よろしくお願いします!

専門家に質問してみよう