プログラミングII 第 7 回 オブジェクトの配列 New, delete 参照 田向.

Slides:



Advertisements
Similar presentations
アルゴリズムとプログラミン グ (Algorithms and Programming) 第6回:クラスとインスタンス クラスの宣言 アクセス修飾子 インスタンスの生成 (new キーワード) this キーワード フィールドとメソッドの実際の定義と使い 方 クラスの宣言 アクセス修飾子 インスタンスの生成.
Advertisements

1 C++ における OOP を用いた 書き方講座 H 山崎貴英. 2 今回の内容 OOP とは? C++ の超基礎 注釈 書いてあるコードはすべて一部抜粋。 コピペだと動かないよ!
C++ 基礎. 目次 C++ とは? C++ におけるオブジェクト指向 課題 C++ とは? Cには足りなかったものが付与されて出来た物 具体的には、 情報の隠蔽(カプセル化) 共通の名前付け(関数のオーバーロード) 再利用の仕組み クラスの導入 など オブジェクト指向 C++ では大規模なプログラミングの.
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
情報工学演習I 第10回 C++の演習2(クラスの継承).
プログラミング基礎I(再) 山元進.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
情報工学演習I 第13回 C++の演習5(仮想関数).
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
アルゴリズムとデータ構造 2011年6月13日
第4回放送授業.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
精密工学科プログラミング基礎Ⅱ 第3回資料 今回の授業で習得してほしいこと: 2次元配列の使い方 (前回の1次元配列の復習もします.)
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
補足説明.
プログラミング論 関数ポインタ と 応用(qsort)
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
情報工学演習I 第12回 C++の演習4(インライン展開).
関数と配列とポインタ 1次元配列 2次元配列 配列を使って結果を返す 演習問題
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
プログラミング入門2 第8回 ポインタ 情報工学科 篠埜 功.
メモリの準備 メモリには、その準備の方法で2種類ある。 静的変数: コンパイル時にすでにメモリのサイズがわかっているもの。 普通の変数宣言
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
第11回 プログラミングⅡ 第11回
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
09: ポインタ・文字列 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
オブジェクトのプロパティ プロパティとは? あたかもそういうメンバー変数(フィールド)がそのクラスに存在するかのように見せる仕組み!
もっと詳しくArrayクラスについて調べるには → キーワード検索
一時的な型 長谷川啓
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
アルゴリズムとプログラミング (Algorithms and Programming)
11: 動的メモリ確保 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
ポインタとポインタを用いた関数定義.
第13回 ポインタ 1 1.
アルゴリズムとデータ構造 2012年6月11日
アルゴリズムとデータ構造1 2009年6月15日
11: 動的メモリ確保 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
第5回 プログラミングⅡ 第5回
11: 動的メモリ確保 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
cp-3. サブクラス,継承 (C++ オブジェクト指向プログラミング入門)
cp-2. 属性,アクセサ (C++ オブジェクト指向プログラミング入門)
コンパイラ 第12回 実行時環境 ― 変数と関数 ― 38号館4階N-411 内線5459
アルゴリズムとデータ構造 2010年6月17日
フレンド関数とフレンド演算子.
演算子のオーバーロード.
11: 動的メモリ確保 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
2005年度 データ構造とアルゴリズム 第2回 「C言語の復習:配列」
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
プログラミング演習II 2003年12月10日(第7回) 木村巌.
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
情報処理Ⅱ 小テスト 2005年2月1日(火).
値渡しと参照渡しについて.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング 3 ポインタ(1).
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
Presentation transcript:

プログラミングII 第 7 回 オブジェクトの配列 New, delete 参照 田向

単項演算子 * 2項演算子: x op y ; 単項演算子: op z ; ポインター 宣言 での * とは違う. 単項演算子 * 2項演算子:  x op y ; 単項演算子:   op z ; ポインター 宣言 での * とは違う. 変数宣言時では ポインター型の変数である事を宣言している.  → 代入演算の時に,コンパイラが型チェックをするのに使用する. Int* p; 単項演算子 * は ポインタ変数 の値から アドレスを取り出して,値取り出しの処理(アドレス・レジスタにアドレスを書き込む)を行う.   x = *p;

単項演算子 & 単項演算子 * と同じように,アドレス操作の 単項演算子 & がある. 単項演算子 & 単項演算子 * と同じように,アドレス操作の     単項演算子 & がある. 単項演算子 & は 変数,オブジェクトのアドレスを取り出す演算. myclass * mp ; myclass myObj ;   mp = &myObj ; int x; int * p , q; p = q ; x = * p ;

オブジェクトのアドレス ポインタ変数 対象(オブジェクト,変数)の アドレスを値として持つ変数 オブジェクトの先頭アドレスを値として持つ 対象(オブジェクト,変数)の      アドレスを値として持つ変数 オブジェクトの先頭アドレスを値として持つ コンパイラはオブジェクト名から先頭アドレスを取り出すことが出来る

オブジェクトのアドレス渡し ポインター変数で渡す オブジェクトが存在している場所を教える. クラス名 * ポインター変数名; で定義する.  オブジェクトが存在している場所を教える. オブジェクトの先頭のアドレス オブジェクトはコピーしない どんなに大きくても先頭アドレスだけがコピーされる オブジェクトのアドレスは      単項演算子 & で取り出せる &で取り出した値はアドレスであるのでポインタ変数にしまう. アドレスにも型があるとエラーチェックができる

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

オブジェクトの配列 #include <iostream> using namespace std; class samp { int a; public: void set_a(int n) { a = n; } int get_a() { return a; } }; int main(){ samp ob[4];  //普通に宣言できる int i; for(i=0; i<4; i++) ob[i].set_a(i); for(i=0; i<4; i++) cout << ob[i].get_a( ); cout << "\n"; return 0; }

初期値の設定も同時に出来る class samp { int a; public: samp(int n) { a = n; } #include <iostream> using namespace std; class samp { int a; public: samp(int n) { a = n; } int get_a() { return a; } }; int main(){ samp ob[4] = { -1, -2, -3, -4 }; int i; for(i=0; i<4; i++)           cout << ob[i].get_a() << ' '; cout << "\n"; return 0; }

2次元配列も容易 5, 6, 7, 8 }; for(i=0; i<4; i++) { class samp { int a; #include <iostream> using namespace std; class samp { int a; public: samp(int n) { a = n; } int get_a() { return a; } }; int main(){ samp ob[4][2] = { 1, 2, 3, 4,               5, 6, 7, 8  }; int i; for(i=0; i<4; i++) { cout << ob[i][0].get_a() << ' '; cout << ob[i][1].get_a() << "\n"; } cout << "\n"; return 0; }

コンストラクタを使った初期化 samp(1, 2), samp(3, 4), samp(5, 6), samp(7, 8), #include <iostream> using namespace std; class samp { int a, b; public: samp(int n, int m) { a = n; b = m; } int get_a() { return a; } int get_b() { return b; } }; int main(){ samp ob[4][2] = { samp(1, 2), samp(3, 4), samp(5, 6), samp(7, 8), samp(9, 10), samp(11, 12), samp(13, 14), samp(15, 16) int i; for(i=0; i<4; i++) { cout << ob[i][0].get_a() << ' ';  cout << ob[i][0].get_b() << "\n"; cout << ob[i][1].get_a() << ' '; cout << ob[i][1].get_b() << "\n"; } cout << "\n";  return 0; }

オブジェクトのポインタ p = ob; // 配列の開始アドレスを取得する int main(){ #include <iostream> using namespace std; class samp { int a, b; public: samp(int n, int m) { a = n; b = m; }; int get_a() { return a; }; int get_b() { return b; }; }; int main(){ samp ob[4] = { samp(1, 2), samp(3, 4),              samp(5, 6), samp(7, 8) }; int i;  samp * p; p = ob; // 配列の開始アドレスを取得する for(i=0; i<4; i++) {  // p ->a = (*p).a cout << p -> get_a( ) << ' '; cout << p -> get_b( ) << "\n"; p + + ; // 次のオブジェクトに進む  } cout << "\n";  return 0; }

練習   次のクラスを使用して,2行5列の2次元配列を作成し,配列内の各オブジェクトに任意の初期値を設定しなさい.次に,配列の内容をポインタを用いて表示しなさい. class a_type { double a, b; public: a_type(double x, double y){ a = x; b = y; } void show(){ cout << a << ‘ ‘ << b << “\n”; };

this pointer class inventory { char item [20]; double cost; #include <iostream> #include <cstring> using namespace std; class inventory { char item [20]; double cost; int on_hand; public: inventory(char * i, double c, int o) { strcpy(item, i); cost = c; on_hand = o; } void show(); }; void inventory::show(){ cout << item; cout << ": $" << cost; cout << " 在庫: " << on_hand << "\n"; } int main(){ inventory ob("レンチ", 4.95, 4); ob.show(); return 0; }

this pointer 明示して記述 class inventory { #include <iostream> #include <cstring> using namespace std; class inventory { char item[20]; double cost; int on_hand; public: inventory(char *i, double c, int o) { strcpy(this -> item, i); // thisポインタを   this -> cost = c; // 使用してメンバに   this -> on_hand = o; // アクセスする } void show(); }; void inventory::show(){ cout << this ->item; // thisポインタを使用してメンバにアクセスする cout << ": $" << this ->cost; cout <<" 在庫:"<< this ->on_hand<<"\n";} int main(){  inventory ob("レンチ", 4.95, 4); ob.show(); return 0; }

New ,delete 演算子 int main(){ int *p; p = new int; // 整数のメモリを確保・割り当てる #include <iostream> using namespace std; int main(){ int *p; p = new int; // 整数のメモリを確保・割り当てる if(!p) { cout << "メモリ割り当てエラー\n"; return 1; } *p = 1000; cout << "pが指している整数型は: " << *p << "\n"; delete p; // メモリを解放する return 0; } mallocにかわる. heap 領域に領域を確保する.

動的オブジェクトを割り当てる class samp { int i, j; public: #include <iostream> using namespace std; class samp { int i, j; public: void set_ij(int a, int b) { i=a; j=b; } int get_product() { return i*j; } }; int main(){ samp *p; p = new samp; // new で オブジェクトを割り当てる if(!p) { cout << "メモリ割り当てエラー\n"; return 1; } p->set_ij(4, 5); cout << "積は: " << p->get_product() << "\n"; return 0; }

動的オブジェクトを割り当てる class samp { int i, j; public: #include <iostream> using namespace std; class samp { int i, j; public: samp(int a, int b) { i=a; j=b; } int get_product() { return i*j; } }; int main(){ samp *p; // オブジェクトを割り当てて初期化する p = new samp(6, 5); if(!p) { cout << "メモリ割り当てエラー\n"; return 1; } cout<<"積は: "<< p->get_product()<<"\n"; delete p; return 0; }

配列のnew, delete p = new int [5]; int main(){ int *p; #include <iostream> using namespace std; int main(){ int *p; // 5つの整数用のメモリを割り当てる p = new int [5]; // 割り当てが成功したことを常に確認する if(!p) { cout << "メモリ割り当てエラー\n";     return 1; } int i; for(i=0; i<5; i++) p[i] = i; for(i=0; i<5; i++) { cout << "整数型p[" << i << "]は: "; cout << p[i] << "\n"; } delete [ ] p; // メモリを解放する return 0; }

オブジェクト配列でのnew,delete #include <iostream> using namespace std; class samp {  int i, j; public: void set_ij(int a, int b) { i=a; j=b; } ~samp() { cout << "デストラクタ呼び出し\n"; } int get_product() { return i*j; } }; int main(){ samp *p; int i; p = new samp [10]; // オブジェクト配列を割り当てる if(!p) { cout << "メモリ割り当てエラー\n"; return 1; } for(i=0; i<10; i++) p[i].set_ij(i, i); for(i=0; i<10; i++) {   cout << "積 [" << i << "] は: "; cout << p[i].get_product() << "\n";  } delete [] p;  return 0; }

参照(reference)&変数 変数の別名(alias)として動作する 用途 関数の引数として参照を渡す. 関数から参照を返す. 独立した参照(非推奨) 効果 関数間でオブジェクトを渡す際,コピーが発生しないため,巨大なオブジェクトを取り扱うプログラムを高速処理可能 左辺で関数が呼べる コピーコンストラクタ,演算子のオーバーロードで利用される.

ポインタ仮引数を使用する場合 #include <iostream> using namespace std; void f(int *n); // ポインタ仮引数を宣言する int main(){ int i = 0; f(&i);  // i のアドレスを取り出す&演算 cout << "iの新しい値: " << i << '\n'; return 0; } void f(int *pn){ *pn = 100; // nが指す引数に100を格納する *演算子: ポインタ変数 pn の値=オブジェクトiのアドレスの場所を取り出す. = 取り出したアドレスの処に100を置く.

参照仮引数を使用する場合 void f(int &n); // 参照仮引数を宣言する int main(){ int i = 0; #include <iostream> using namespace std; void f(int &n); // 参照仮引数を宣言する int main(){ int i = 0; f(i); cout << "iの新しい値: " << i << '\n'; return 0;  } // f( )関数は参照仮引数 & を使用する void f(int &n) {  // int &n = i; と同じ意味  // 次の文では * が必要ない *n=100  // n は i の別名である n = 100; // f()関数を呼び出すのに使用した引数nに100を格納する

参照の例-I void swapargs(int &x, int &y); int main(){ int i, j; #include <iostream> using namespace std; void swapargs(int &x, int &y); int main(){  int i, j; i = 10;  j = 19; cout << "i: " << i << ", "; cout << "j: " << j << "\n"; swapargs(i, j); cout << "交換後: "; cout << "j: " << j << "\n";   return 0; } void swapargs(int &x, int &y){   int t; t = x;  x = y;   y = t;  }  x , y はi, j の別名なので,  i, jの値が交換される.

参照の例-II class myclass { int who; public: myclass(int n) { who = n; #include <iostream> using namespace std; class myclass { int who; public: myclass(int n) { who = n; cout<<"コンストラクタ呼び出し"<<who<< "\n"; } ~myclass() { cout << "デストラクタ呼び出し " << who << "\n"; } int id( ) { return who; } }; void f(myclass &o){ // oを参照によって渡す    // .演算子を使用していることに注意 cout << "受け取り " << o.id() << "\n"; } int main(){ myclass x(1); f(x); //fでXはコピーされない.fを抜ける時に      //デストラクタ ~myclass は呼ばれない  return 0; }

参照を返す関数の効能-I char &array::put(int i){// 配列に情報を格納する class array { #include <iostream> #include <cstdlib> using namespace std; class array {  int size; char *p; public: array(int num); ~array() { delete [] p; } char &put(int i); char get(int i);  }; array::array(int num){ p = new char [num]; size = num;  } char &array::put(int i){// 配列に情報を格納する return p[i]; // p[i]への参照を返す 

参照を返す関数の効能-II // Get something from the array. char array::get(int i){  return p[i]; // 文字を返す } int main(){ array a(10);  //左辺で関数が呼べる.普通の関数では不可  // 戻り値がアドレスだから出来る.  a.put(3) = ‘X’; a.put(2) = ‘R’;  cout << a.get(3) << a.get(2); cout << "\n"; return 0; 

独立参照 #include <iostream> using namespace std; int main() { int x; int &ref = x; // 独立参照を作成する x = 10; // この2つの文の ref = 10; // 機能は同等である ref = 100; // 100を2回出力する cout << x << ' ' << ref << "\n"; return 0; } refはxの別名である. 使用さえる事は少ない.

次のプロトタイプ宣言を利用して,orderで指定された桁数までnumの桁数を上げるmag()という関数を作成せよ. 練習   次のプロトタイプ宣言を利用して,orderで指定された桁数までnumの桁数を上げるmag()という関数を作成せよ. 例えば,num = 4, order = 2 のとき,関数 mag() が終了したとき num = 400 になるようにせよ. void mag(long &num, long order);

まとめ:オブジェクトは物 物objectの情報classは存在する. 抽象classから具体化classの流れ(派生).  物には内部構造(メンバー)がある.  物objectの中には物objectsがある.  物の中では物が同じように相互に関係している. Classという情報として存在している. 画像,音,物理的,数学的,情報的に存在するものは物: オブジェクトである. Windows, AV関連プログラムは物を扱う. 処理(プログラム)も物としてやり取りする. Applet (application + let(小さい)) 回路も物,HDL,LSI回路,仮想回路

WindowsもCRT画面内の物 myWindow-1 myWindow-3 myWindow-2 progII > myWindows::windows(…){…} Rootはwindow OSでCRT全体. すべてのwindowは,window OSにつながっている. Windos OSにメッセージを送って,それぞれのwindow オブジェクトに対して処理を行う.

Turbo C++によるアプリ例 フリーのIDEであるTurbo C++を利用したアプリの作成例を紹介する. Windows アプリの基本的部品である,Windowやボタン,画像格納領域等は全て開発環境内に準備されているクラスからオブジェクトを生成して利用する. 上記クラスの具体的な実装方法は知る必要が無い. 上記クラスの利用方法,すなわちメンバ変数やメンバ関数,継承関係などはヘルプやWEBで検索可能.