プログラミングII 第 5 回 関数へのObject渡し 値,ポインター 田向 前回までの復習 クラスとオブジェクト • データ構造を設計して決めるのが class ABC {…}; • このデータ構造でメモリ領域を確保 して,オブジェクトとして宣言する. ABC obj1; ABC obj2; • オブジェクトに対して操作する. – 初期化, – 入出力など • クラスには,メンバー変数,メンバー 関数が定義できる. – focus で見える,見えない • public, private など C++プログラム作成・実行 • クラスをヘッダー・ファイル xxxxx.H に作る. • クラスにはメンバー変数,メンバー 関数の宣言を書く. • 実装コードを xxxxx.cppファイル に書く. – Class_name::func(…){…}; • main{・・・}でオブジェクトを生成し て,メンバー関数を呼んで,メン バー変数の読み書きを行う. • メンバー変数の中でも,オブジェクト を生成することが出来る. コンストラクタ,デストラクタ • メモリに動作領域を確保するのがコ ンストラクタ – 以前のコンパイラーは自動で暗 黙裡にやっていた – ユーザーが明確に書かなければ ならない. • OS(システム)管理のメモリを要求 する.Cではmalloc()がしていた. • 面倒だか,ダンプ記述(cout等)を すればデバッグが容易になる • 不要になったメモリを開放するのが デストラクタ • 要するに オブジェクトは生成され, 使用され,破棄される. – なれるのは大変だが,大事 関数,メンバー関数 • Cでは関数の引数では値渡し. – 引数の値を取り出して関数に 送っている. – ポインタ変数に対して 変数のア ドレスを値として渡している. – 渡された値をアドレスと解釈して メモリへの読み書きをしている. – C++でも同じで値渡しである. • 関数の引数がオブジェクトの場合に はどうする? – オブジェクトの値とは,一つでな い. – メンバー変数以外にメンバー関 数もある.メンバー関数の値は何 か?考えなくてはいけない. 関数引数に関する オブジェクトの扱い方 関数へのobjectの引渡し:内容 • C,C++では値渡しが原則 – オブジェクトの値を渡す? • オブジェクトそのままをコピーして渡 す.オブジェクトが大きいと大変. • 一時的に,オブジェクトが作られる. – コンストラクタが呼ばれる? – コンストラクタは初期化用であり,今の 値とは違う. – コピー・コンストラクタと言うものがある • コンパイラーが影で名前をつける. • 関数を抜けるときに廃棄される. – デストラクタが呼ばれる. – オブジェクトの代入と同じ • 元のオブジェクトには影響が無い • オブジェクトの中に動的なメモリが あると問題がある. 関数へのobjectの引渡し:例 #include <iostream> using namespace std; class samp { int i; public: samp(int n) { i = n; } int get_i() { return i; } }; int sqr_it( samp o ) { return o.get_i() * o.get_i(); } int main() { samp a(10), b(2); cout << sqr_it(a) << "\n"; cout << sqr_it(b) << "\n"; return 0; } Objectの値渡し:例2 #include <iostream> using namespace std; class samp { int i; public: samp(int n) { i = n; } void set_i(int n) { i = n; } int get_i() { return i; } }; void sqr_it(samp o) { o.set_i(o.get_i() * o.get_i()); cout << "iのコピーの値は " << o.get_i(); cout << "\n"; } int main(){ samp a(10); sqr_it(a); // 値呼び出し cout << "しかし、a.iはmain()で変更されない: "; cout << a.get_i(); return 0; } オブジェクトのアドレス • ポインタ変数 – 対象(オブジェクト,変数)の アドレスを値として持つ変数 – オブジェクトの先頭アドレスを値として 持つ – コンパイラはオブジェクト名から先頭ア ドレスを取り出すことが出来る s1 strtype * sp1; sp1= &s1; ベースアドレス f IE L D N A M E 1 f IE L D N E M E 2 オブジェクトのアドレス渡し • ポインター変数で渡す クラス名 * ポインター変数名; で定義する. – オブジェクトが存在している場所 を教える. • オブジェクトの先頭のアドレス • オブジェクトはコピーしない – どんなに大きくても先頭アドレスだけが コピーされる – オブジェクトのアドレスは 単項演算子 & で取り出せる • &で取り出した値はアドレスである のでポインタ変数にしまう. • アドレスにも型があるとエラーチェッ クができる Objectのアドレス渡し #include <iostream> using namespace std; class samp { int i; public: samp(int n) { i = n; } void set_i(int n) { i = n; } int get_i() { return i; } }; void sqr_it(samp *o){ o->set_i(o->get_i() * o->get_i()); cout << "iのコピーの値は " << o->get_i(); cout << "\n"; } int main(){ samp a(10); sqr_it(&a); cout << "今、main()は変更された: "; cout << a.get_i(); return 0; } オブジェクトの返しI 関数からの返り値も引数渡しと同じ? • オブジェクトを返す時,オブジェクト はコピーされるのか? – 一時的なオブジェクトが作られる. このオブジェクトは何時,開放さ れるのか? • 関数を抜けた時では,使えない. • どこかに代入された後. – デストラクタが呼ばれる. この処理は判り難い.これに起因 するエラーは頻繁に起こる. オブジェクトの返しII #include <iostream> #include <cstring> using namespace std; class samp { char s[80]; public: void show() { cout << s << "\n"; } void set(char *str) { strcpy(s, str); } }; samp input(){ char s[80]; samp str; cout << "文字列の入力: "; cin >> s; str.set(s); return str; } int main(){ ob = input(); ob.show(); return 0; } samp ob; オブジェクトを返す時に起きるエラー #include <iostream> #include <cstring> #include <cstdlib> using namespace std; class samp { char *s; public: samp() { s = '\0'; } ~samp() { if(s) free(s); //動的メモリ注意が必要 cout << "sを解放\n"; } void show() { cout << s << "\n"; } void set(char *str); }; void samp::set(char *str){ s = (char *) malloc(strlen(str)+1); if(!s) { cout << "メモリ割り当てエラー\n"; exit(1); } strcpy(s, str); } デストラクタが3回呼ばれる. samp input( ){ char s[80]; samp str; cout << "文字列の入力: "; cin >> s; str.set(s); return str; } int main( ) { samp ob; ob = input(); //ここで 問題が発生する ob.show(); return 0; } C++の作成手順 • • 必要なClassを作成する. • • 空の場所だけを作る. 空の関数を作る. Class間の取り決めを作る. 1. 必要な情報,変数を決める. 2. やり取りするメッセージを決める. 1. データ,命令,関数 • 関数の中身を記述する. 1. オブジェクトを生成する. 2. オブジェクト間の処理を書く. • オブジェクト間でのメッセージのやり取り で処理が進んでいく. 手続き型のプログラム 1. 今までは,処理の流れを先に決める. 2. 次に,必要な変数,配列を決める. 3. 変数の値を取り出し,計算して, 4. 計算結果を変数に入れる.---これの繰り 返し, 5. 条件と制御: – さらに,複数の条件でもプログラムが 動くように条件文を加える. • 関数: 処理の流れの中で使われる. 変数を持ってくる. 計算結果を書き込む. 何処から変数を持ってきて, 何処にしまうか C++の作成手順 II • • • • • 処理中心から,データ中心に大きく変更 処理は,データ:オブジェクトの付属物. オブジェクトが他のオブジェクトに作用. オブジェクト間の関係,相互作用が重要 オブジェクト全体を大局的に決めれば,オ ブジェクト相互の関係は局所的, すなわち,局所的な変更の影響は 全体に及ばない. オブジェクトをもっと自由に使う やって見ることが大事. 慣れるまで,何でもクラスにできるか考えて みる. 処理は後回し クラスの関係に注目する.
© Copyright 2025 ExpyDoc