情報工学演習I 第10回 C++の演習2(クラスの継承).

Slides:



Advertisements
Similar presentations
1 C++ における OOP を用いた 書き方講座 H 山崎貴英. 2 今回の内容 OOP とは? C++ の超基礎 注釈 書いてあるコードはすべて一部抜粋。 コピペだと動かないよ!
Advertisements

プログラミング演習( 2 組) 第 9 回
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第3回 配列(1) 情報・知能工学系 山本一公
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第4回 配列(2) 情報・知能工学系 山本一公
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
1.1 C/C++言語 Hello.ccを作りコンパイルしてa.outを作り出し実行する
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング基礎I(再) 山元進.
第13回構造体.
配列(2) 第10回[平成15年6月26日(木)]:PN03-10.ppt 今日の内容 1 素数を求める(教科書の例):復習
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
アルゴリズムとプログラミング (Algorithms and Programming)
情報工学演習I 第13回 C++の演習5(仮想関数).
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
プログラミング入門2 第1回 導入 情報工学科 篠埜 功.
プログラミング演習(2組) 第12回
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
配列の扱い、探索 有効範囲と記憶域期間 第12回 [7月10日、H.15(‘03)] 今日のメニュー 1 前回の課題の復習
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
プログラミングII 第 7 回 オブジェクトの配列 New, delete 参照 田向.
補足説明.
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
プログラミング言語入門 手続き型言語としてのJava
情報工学演習I 第12回 C++の演習4(インライン展開).
オブジェクト指向 プログラミング 第二回 知能情報学部 新田直也.
関数の定義.
プログラミング演習(2組) 第8回
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
C#言語ソースプログラムの原型 C言語 C#言語 Hello World! Hello Students! オマジナイ! 適当なクラス名
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
C言語 はじめに 2016年 吉田研究室.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
プログラミング入門 電卓を作ろう・パートI!!.
アルゴリズムとプログラミング (Algorithms and Programming)
ネットワーク・プログラミング Cプログラミングの基礎.
第5回 プログラミングⅡ 第5回
JAVA入門⑥ クラスとインスタンス.
標準入出力、変数、演算子、エスケープシーケンス
cp-3. サブクラス,継承 (C++ オブジェクト指向プログラミング入門)
cp-2. 属性,アクセサ (C++ オブジェクト指向プログラミング入門)
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2003年12月10日(第7回) 木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
プログラミング入門2 第3回 条件分岐(2) 繰り返し文 篠埜 功.
printf・scanf・変数・四則演算
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

情報工学演習I 第10回 C++の演習2(クラスの継承)

授業の予定(後半) # 月日 内容 担当者 7 11月13日 C言語の演習4 (ポインタの演算,列挙型) 内海 8 11月20日 9 11月27日 C++の演習1(クラス) 岩村 10 12月 4日 C++の演習2(クラスの継承) (代理:谷川) 11 12月11日 C++の演習3(仮想関数) 12 12月18日 C++の演習4(インライン展開) 13 1月 8日 C++の演習5 (関数のオーバロード) 14 1月15日 C++の演習課題 谷川 15 1月22日 総合演習

先週紹介しましたが、継承が入っていないので、お勧めできないと思いました 参考書(追加) 参考書 (D)「新版 明解C++ 入門編」 柴田 望洋 (著) 先週紹介しましたが、継承が入っていないので、お勧めできないと思いました

今日の内容 第7回演習課題の解説 クラスの継承 newとdelete コンストラクタ、デストラクタ 配列の動的メモリ確保 オブジェクトのメモリ確保 コンストラクタ、デストラクタ

第7回演習課題の解説

第7回演習課題(1) 0から99までの値をとる乱数を1000個発生させ,発生した 乱数の0から99までの頻度を計算し,出力するプログラム を作成せよ.頻度の計算は要素が100個ある配列を使って 行うこと.また,配列の値の変更は,ポインタ演算をして 行うこと. 頻度:0が2回,1が2回出現 配列を用意して,乱数の値に応じて頻度を計算 配列のアクセスの方法 × hist[ r ]++; 〇 (*(hist + r ))++; など, []演算子を使わない

第7回演習課題(2) 授業支援システムにあるtext.txt をダウンロード し,このテキストファイルから整数のデータを読 みこんで動的に確保したメモリに格納し,値の平 均,分散,中央値,最頻値を求めるプログラムを 作成せよ.ファイルの形式は,はじめの1行目に 整数の数が書かれており,次の行以降は空白区切 りの整数のデータが列挙されている. text.txt の1行目の値を読み込む 1行目の値をもとにメモリをmalloc で確保し,値を読み込 む 平均値などの計算は第5回演習課題の課題2の関数を利用

第7回演習課題(3) 曜日を列挙型で表現し,switch 文を使って列挙 型の曜日ごとに,自己の時間割を示すプログラ ムを作成せよ. enum 型で曜日を以下のように定義 enum week { sunday, monday, tuesday, wednesday, thursday, friday, saturday }; enum 型変数を分岐の式として利用

第7回演習課題(4) 3次多項式 を の形に因数分解したときのa, b, c の 値を計算し,出力するプログラムを作成せよ. 3次多項式              を         の形に因数分解したときのa, b, c の   値を計算し,出力するプログラムを作成せよ. ただし0<a<b<c とし,a, b, c は整数となる. 3次多項式が0 になるx がa, b, c となる x=1, 2,… と代入し,3次多項式が0 になるx を小さいもの からa, b, c とすればよい

クラスの継承

電卓プログラムの作成 以下では、電卓の振る舞いをするクラスを作って、 電卓を実現 クラスの継承 加減算対応型計算機(ex6_calculator1.cc) クラスCalculator1を定義 足し算と引き算に対応 数値のクリアができる 現在の値を返すことができる 四則演算対応型計算機(ex7_calculator2.cc) クラスCalculator2を定義 クラスCalculator1の機能に加えて、かけ算と割り算に対応 クラスの継承

クラスの継承とは 既存のクラスの機能を引き継ぎ、一部のみを変更で きる機能 メリット プログラムの変更を最小限にできる 新しいデータメンバの追加 新しいメンバ関数の追加 既存のデータメンバの上書き 既存のメンバ関数の上書き メリット 過去に作ったクラスのインタフェース(関数の引数、戻り 値の仕様)を変更することなく、機能を追加できる プログラムの変更を最小限にできる

クラスの継承とは 用語 基本クラス 継承されるクラス(この例ではCalculator1) 派生クラス

コンストラクタの中で関数を呼び出すこともできる 計算機(加減算のみ) ex6_calculator1.cc #include <iostream> using namespace std; class Calculator1 { private: double val; // 計算機内部で記憶して いる値 public: Calculator1() { // コンストラクタ clear(); // 値のクリア } void clear() { // 値のクリア val = 0; } double add(double val2) { // 足す val += val2; return val; double sub(double val2) { // 引く val -= val2; // 現在の値を返す double get_val() { }; コンストラクタの中で関数を呼び出すこともできる

計算機(加減算のみ) ex6_calculator1.cc 続き int main() { string ope; // コマンド入力用 double n; // 数値入力用 Calculator1 calc; // 計算機のオブジェクトを作る cout << "Input an operation and a number separated by space (ex. \"+ 10\" to add 10)." << endl << "Input \"=\" to show the current value." << endl << "Input \"clear\" to clear." << endl << "Press Ctrl+c to quit." << endl; cout << "Current value: " << calc.get_val() << endl;

計算機(加減算のみ) ex6_calculator1.cc 続き while(1) { // 無限ループ cin >> ope; // キーボードからコマンドを入力する if (ope=="+") { // コマンドが "+" か調べる cin >> n; // キーボードから数字を入力する cout << "Result: " << calc.add(n) << endl; continue; // 無限ループの最初に戻る } if (ope=="-") { // コマンドが "-" か調べる cout << "Result: " << calc.sub(n) << endl;

計算機(加減算のみ) ex6_calculator1.cc 続き if (ope=="=") { // コマンドが "=" か調べる cout << "Current value: " << calc.get_val() << endl; continue; // 無限ループの最初に戻る } if (ope=="clear") { // コマンドが "clear" か調べる calc.clear(); cout << "Result: " << calc.get_val() << endl; cout << "Invalid command! ignored." << endl; return 0;

緑色の文字はユーザーが入力したものを表す 実行例 $ ./a.exe Input an operation and a number separated by space (ex. "+ 10" to add 10). Input "=" to show the current value. Input "clear" to clear. Press Ctrl+c to quit. Current value: 0 + 10 Result: 10 + 100 Result: 110 緑色の文字はユーザーが入力したものを表す

実行例(続き) - -50 Result: 160 - 1000 Result: -840 clear Result: 0 + 10 Result: 10 = Current value: 10

計算機(四則演算対応) ex7_calculator2.cc ここだけ変更 クラスCalculation1は ほぼそのまま #include <iostream> using namespace std; class Calculator1 { protected: // 継承したクラスと共有す るために,protectedにする double val; // 計算機内部で記憶して いる値 public: Calculator1() { // コンストラクタ clear(); // 値のクリア } void clear() { // 値のクリア val = 0; } double add(double val2) { // 足す val += val2; return val; double sub(double val2) { // 引く val -= val2; // 現在の値を返す double get_val() { }; ここだけ変更 クラスCalculation1は ほぼそのまま

クラスCalculation2を新たに追加 計算機(四則演算対応) 続き ex7_calculator2.cc class Calculator2 : public Calculator1 { public: // 掛ける double mul(double val2) { val *= val2; return val; } double div(double val2) { val /= val2; }; クラスCalculation1を継承した クラスCalculation2を新たに追加

計算機(四則演算対応) 続き ex7_calculator2.cc クラスCalculator1のオブジェクトから int main() { string ope; // コマンド入力用 double n; // 数値入力用 Calculator2 calc; // 計算機のオブジェクトを作る cout << "Input an operation and a number separated by space (ex. \"+ 10\" to add 10)." << endl << "Input \"=\" to show the current value." << endl << "Input \"clear\" to clear." << endl << "Press Ctrl+c to quit." << endl; cout << "Current value: " << calc.get_val() << endl; クラスCalculator1のオブジェクトから クラスCalculator2のオブジェクトに変更

計算機(四則演算対応) 続き ex7_calculator2.cc while(1) { // 無限ループ cin >> ope; // キーボードからコマンドを入力する if (ope=="+") { // コマンドが "+" か調べる cin >> n; // キーボードから数字を入力する cout << "Result: " << calc.add(n) << endl; continue; // 無限ループの最初に戻る } if (ope=="-") { // コマンドが "-" か調べる cout << "Result: " << calc.sub(n) << endl;

クラスCalculation2で新たに加わった 計算機(四則演算対応) 続き ex7_calculator2.cc if (ope=="*") { // コマンドが "*" か調べる cin >> n; // キーボードから数字を入力する cout << "Result: " << calc.mul(n) << endl; continue; // 無限ループの最初に戻る } if (ope=="/") { // コマンドが "/" か調べる cout << "Result: " << calc.div(n) << endl; クラスCalculation2で新たに加わった かけ算、割り算の処理を追加

計算機(四則演算対応) 続き ex7_calculator2.cc if (ope=="=") { // コマンドが "=" か調べる cout << "Current value: " << calc.get_val() << endl; continue; // 無限ループの最初に戻る } if (ope=="clear") { // コマンドが "clear" か調べる calc.clear(); cout << "Result: " << calc.get_val() << endl; cout << "Invalid command! ignored." << endl; return 0;

派生クラスからアクセスできるようにprotectedに変更 クラスの継承で気をつけること、その1 基本クラスのメンバが派生クラスからアクセスでき ること ex6_calculator1.cc class Calculator1 { private: double val; // 計算機内部で記憶している値 ex7_calculator2.cc 派生クラスからアクセスできるようにprotectedに変更 class Calculator1 { protected: // 継承したクラスと共有するために, protectedにする double val; // 計算機内部で記憶している値

クラスの継承で気をつけること、その1 基本クラスのメンバのアクセス制御 続き public クラス外からアクセス可能 private protected 基本的にはprivateと同じだが、派生クラスからはアクセ ス可能

クラスCalculation2を新たに追加 クラスの継承で気をつけること、その2 基本クラスのアクセス制御 この「public」の部分によって、継承の挙動が変わる public: 基本クラスの公開メンバが派生クラスの公開メン バとして扱われる private:基本クラスの公開メンバが派生クラスの非公開メ ンバとして扱われる 何も指定しないときは、privateとして扱われる わかりやすさのために、明示的に指定する方がいい クラスCalculation1を継承した クラスCalculation2を新たに追加 ex7_calculator2.cc class Calculator2 : public Calculator1 {

newとdelete (配列の動的メモリ確保)

メモリの容量をsizeof演算子で計算しないといけないし、キャストも必要。 配列の動的メモリ確保・解放 メモリの容量をsizeof演算子で計算しないといけないし、キャストも必要。 面倒だった C言語の場合 mallocでメモリの確保 freeでメモリの解放 ex8_malloc.c #include <stdlib.h> /* mallocを使うときのお約束 */ int main() { int *n; n = (int *)malloc(sizeof(int)*10); /* int型の変数10個分のメモリ確保 */ free(n); /* 確保したメモリの開放 */ return(0); }

重要:配列のメモリ確保のときは、[]が必要 配列の動的メモリ確保・解放 C++の場合 newでメモリの確保 配列の大きさが1のときは、 n=new int; とすれば良い delete []でメモリの解放 sizeof演算子もキャストも不要 重要:配列のメモリ確保のときは、[]が必要 int main() { int *n; n = new int[10]; // int型の変数10個分のメモリ確保 delete [] n; // 確保したメモリの開放 return(0); } ex9_new_array.cc

newとdelete (オブジェクトのメモリ確保)

#include <string> // stringを使うために必要 #include <iostream> // 入出力に必要 using namespace std; // お約束 class Account { public: string name; // 名前 int balance; // 残高 }; int main() { Account *suzukip; suzukip = new Account(); // Account型のオブジェクトを作成 suzukip->name = "鈴木龍一"; // 鈴木さんの名前 suzukip->balance = 123000; // 鈴木さんの残高 cout << suzukip->name << "様の残高は" << suzukip->balance << "円で す." << endl; delete suzukip; // 確保したメモリの開放 return 0; } ex10_new_obj.cc

クラスのメモリ確保 これはコンストラクタに渡す引数がない場合 構造体と同じ newでメモリの確保 まず、クラスのポインタを宣言 Account *suzukip; newによるオブジェクトの作成 suzukip = new Account(); クラスのポインタ メンバへのアクセスは”.”の代わりに、”->”を使う ○ suzukip->balance ○ (*suzukip).balance × suzukip.balance deleteでメモリの解放 これはコンストラクタに渡す引数がない場合 構造体と同じ ポインタに*を付けると、Account*型からAccount型になるので 重要:オブジェクトのときは、[]をつけない

コンストラクタ、デストラクタ

コンストラクタとデストラクタ クラスの特別なメンバ関数 コンストラクタ オブジェクトが作られるときに呼ばれる関数 デストラクタ オブジェクトが破棄されるときに呼ばれる関数

確保していない配列のメモリ開放を避けるために,sizeを0にしておく クラス内でのメモリ確保例 ex11_constructor.cc #include <iostream> using namespace std; // オブジェクト作成時に動的にメモリを確保し,破棄時にメモリを開放す るクラス class dyn_mem { public: int *array; // 配列用のポインタ int size; // 配列の大きさ dyn_mem() { // デフォルトコンストラクタ size = 0; // 配列のサイズが指定されないときは,配列のメモリを確保 しない } 確保していない配列のメモリ開放を避けるために,sizeを0にしておく

クラス内でのメモリ確保例 続き ex11_constructor.cc dyn_mem(int _size) { // コンストラクタ cout << "Constructor is called." << endl; size = _size; cout << "Memory is allocated." << endl; array = new int[size]; // 配列のメモリ確保 } ~dyn_mem() { // デストラクタ cout << "Destructor is called." << endl; if (size!=0) { // 配列にメモリが確保されている場合のみ,メモリを開放する cout << "Memory is released." << endl; delete [] array; size = 0; };

ブロック内で宣言された変数(オブジェクト)は、ブロックが終わると破棄される クラス内でのメモリ確保例 続き ex11_constructor.cc int main() { { cout << "A" << endl; dyn_mem dm(10); // オブジェクトの作成(大きさが10の配列の メモリを確保) cout << "B" << endl; } cout << "C" << endl; return 0; ブロック ブロック内で宣言された変数(オブジェクト)は、ブロックが終わると破棄される

実行例 オブジェクトが作られて、メモリが確保された $ ./a.exe --A-- Constructor is called. Memory is allocated. --B-- Destructor is called. Memory is released. --C-- オブジェクトが破棄されて、メモリが解放された

演習課題

第10回演習課題(1) 1. 以下の仕様を満たすプログラムを作れ 以下の仕様を満たすクラスを持つ 第9回演習課題(1)で作成したクラスを継承する 数学、理科、英語に加えて、国語の点数を保存すること ができる 合計4教科の点数を変更(上書き)できる関数と照会で きる関数がある 合計4教科の点数の平均を計算して返す関数がある 上記のクラスを用いて、2人分のデータ(名前、4教科の 点数)を順次コマンドラインから入力できる 全員分の情報を入力した後、一人ずつ名前と平均点を表示 する

第10回演習課題(2) 2. 以下の様に分割コンパイルを実現せよ 第9回演習課題(2)で作成したプログラムを以下の3つ に分割する main関数を含むファイル クラスのヘッダファイル クラスのメンバ関数の定義を含むファイル コンパイルするコマンドをテキストファイルに書く 例: g++ -c ex5_main.cc g++ -c ex5_coordinate.cc g++ ex5_main.o ex5_coordinate.o ソースファイル(3つ)とコンパイルするコマンドを提出

第10回演習課題(3) 3. 以下のプログラムを作成する 引数を2つ取る 1つはファイル名 もう一つは、キーワード ファイルの中にキーワードが何回出現するかを数える

コンストラクタ、デストラクタを説明した場合のみ 第10回演習課題(4) コンストラクタ、デストラクタを説明した場合のみ 4. 以下のプログラムを作成する 以下の仕様を満たすクラスを作れ オブジェクト作成時に整数kを引きとし、newを使って (k+1)*(k+1)の2次元配列を確保する オブジェクト破棄時にdeleteでメモリを解放する 任意の座標(x,y)に値を代入できる 任意の座標(x,y)の値を表示できる

第10回演習課題(4) 続き k=4のとき 行毎の和 合計 列毎の和 (0,0)から(k-1,k-1)までには、乱数で適当な値を入れる 列毎の和を(k,0)から(k,k-1)に入れる 行毎の和を(0,k)から(k-1,k)に入れる (0,0)から(k-1,k-1)までの合計を(k,k)に入れる (0,0)から(k,k)までを出力した後、オブジェクトを破棄する (0,0) (0,1) (0,2) (0,3) (0,4) (1,0) (1,1) (1,2) (1,3) (1,4) (2,0) (2,1) (2,2) (2,3) (2,4) (3,0) (3,1) (3,2) (3,3) (3,4) (4,0) (4,1) (4,2) (4,3) (4,4) k=4のとき 行毎の和 合計 列毎の和

提出に関して 提出するもの ソースファイル(.ccまたは.cpp ファイル) ファイル名はkadai1204_学籍番号_課題番号.cc(.cpp) (Visual Studioの場合) ファイル名はkadai1204_学籍番号_課題番号_v.cc (.cpp) 実行結果の出力と講義に関するコメント .txt ファイルで、学籍番号、氏名を含む ファイル名はreport1204_学籍番号.txt とする

提出に関して(続き) 提出期限 提出方法 注意点 12月18日(水) 00:00 授業支援システムから提出 12月18日(水) 00:00 提出方法 授業支援システムから提出 注意点 ファイル名の命名規則が間違っているものは採点しない コンパイルの通らないものは採点しない