:第三章 クラスの詳細
クラスの詳細。だんだんこう、C++って考えることが多くて大変! という気分になってきた。
オブジェクトの代入
myclass a,b; a = b;
とすると、aにbがコピーされる。javaとかと違って変数が同じクラスを参照するわけではなく、配列なども含めたメンバ変数も全部コピーされる。
メンバ変数にポインタを持ち、デストラクタでそれをフリーするようなクラスでオブジェクトの代入が行われた場合、同じ領域が二回freeされるのでエラーがおきる。
関数へのオブジェクトの引き渡し
オブジェクトを引数として渡した場合、デフォルトでは全て値渡し=オブジェクトのコピーが渡される。関数内で引数のオブジェクトに変更を加えても、外には影響がない。
関数から抜けるときに引数のコピーのオブジェクトのデストラクタが呼び出されるので、デストラクタにfree()がある場合、オブジェクトの代入と同様の問題が発生する。(デストラクタが二回呼び出される)
class myclass{ char *s; public: myclass(char a){s = (char *)malloc(strlen(a));strcpy(s,a);} ~myclass(){free(s);} }; myclass f(myclass a){ return a; }//ココでm0のコピーのデストラクタが呼び出され、sが解放される。 main(){ myclass m0("test"); f(m0); return 0; }//ココでm0のデストラクタが呼び出され、sをもう一度解放しようとしてエラーになる。
という感じで良いのかな。今適当にかいたから動かなそうなコードだけど。
オブジェクトのポインタを渡せば、関数内でオブジェクトを弄ることが出来る。
関数からのオブジェクトの返し
関数からオブジェクトを返すとき、オブジェクトを呼び出し元に返した後(オブジェクトがコピーされて返される)、オブジェクトは破棄される。その際デストラクタが呼び出されるので、以下略。
例の3.3.2でデストラクタが三回呼び出されると書いてあるけど、実行してみたら二回しか呼び出されなかった。
class samp2{ char *s; public: samp2() {s = '\0';} ~samp2() {cout << "free s\n";if (s) free(s);} void show() {cout << s << "\n";} int set(char *str); }; int samp2::set(char* str){ s = (char *)malloc(strlen(str)+1); if(!s){ cout << "Memory Allocation Error\n"; exit(1); } strcpy(s , str); } samp2 input(){ char s[80]; samp2 str; cout << "input string:"; cin >> s; str.set(s); return str;//strが一時オブジェクトにコピーされ戻り値として元ルーチンに返される。 }//1.スコープから外れるときにstrのデストラクタが呼び出される int main(){ samp2 ob; ob = input();//2.一時オブジェクトのデストラクタが呼び出される ob.show(); return 0; }//3.obのデストラクタが呼び出される。
勿論エラーにはなったけど。どうも2.が実行されていない気がする。
なんだろう、コンパイラの違いかなあ。
そもそも、一時オブジェクトが何かよくわからない。