プログラミング・演習II

オブジェクト指向プログラミング
C++勉強会第1回
田向
準参考書: 独習C++ 第3版
ハーバート・シルト
出版社:翔泳社
講義内容I
C++オブジェクト指向プログラミングを習得
– プログラム-I,Cの復習ではない.
– 制御文,配列(ポインタ),関数が使え
ることが前提.
• 情報,LSI等設計分野大規模ソフトを対
象
– 大規模ソフトウェア作成技術必須
– 複雑・多様なデータ構造とアルゴリズム
• 画像,音声,データベース
• 可変配列,MAP,Priority Queque
• イベント処理
• ハードウェアとソフトウェアとを統合
– C++とHDLとの比較
– プロセッサ,LSI分野
• オブジェクト指向設計により
– 論理回路,神経回路を作る.
講義内容II
1. C++の概要
2. クラスの概要 構造体→クラス
– メンバー,メンバー関数
– コンストラクタ-,デストラクタ3. クラスの詳細
4. 配列,ポインタ,参照
5. 関数,オーバーロード
6. 演算子,オーバーロード
7. 継承
8. 仮想関数,
9. テンプレート,例外処理
10. 標準テンプレートライブラリ(STL)
– Map,priority queue
授業の仕方と要点
• 独習C++の例に沿って解説.
– 講義目標を実現するオブジェクト設計
– 自習が必須! しないと多分X
• gcc
– iMAC に組み込まれている。
• 演習
– IDE( XCODE)により簡単に開発
– 始めからC++になれた方が早い:細かいこと
(文法)は気にしない.
• 言葉であるからまず,習うより慣れろ!
• ひたすら書いて,デバッグ.
• 何を考えて何を表現するか
– 実行コードが大きくても遅くても気にしない
– 標準ライブラリを使う
• 簡単に判り易く書く
• 動く事が大事.内部の難しいことは考えない
• 演習レポートと期末試験で成績.
CからC++へ,何故?
• 手続き型言語
– FORTRAN,Pascal,A, B, C, Javaへ
•
•
•
•
ブラック・ボックスのモデル
Subroutine,procedure,function
Calling,関数読み出しの塊
この境界を越えてデータが変更される
• 複雑で大規模なソフト
– ソフトウェア危機(70年代)
– 数値から文字処理
– 失敗やバグが多発
• 新しい言語を模索
–
–
–
–
–
–
LISP
Smalltalk
宣言型言語(prolog),
関数型言語
Hardware Description Language(HDL)
D
大規模システム開発での経験
• ヘッダーファイルは,変数、構造
体、関数、クラス等のメモ帳
• 変数に名前があれば存在
– 次々と名前を付けて作る.使い
方は後で.
– データ構造は利用する時に決め
る
• 関数も名前がつけば存在
– 中の処理は後回し,
– 関数の呼ばれ方(何時,何処で,
誰が,何で呼んだか,どうやって)
次々と決める
データと関数をまとめる
クラスの主体
メモリ・アクセス
• 配列からポインターへ
• 配列:同じ物を添え字をつけて並べ
る。→ Int型変数とfloat型変数を
混ぜることは出来ない。
• 配列名→メモリでの開始位置を決
めている。
• 配列の大きさ→メモリ領域の確保
メモリ内での位置の制御を行って
いるだけ
• ポインタ型変数:メモリのアドレスを
値に持つことが出来る変数。 Int型
変数等と同じようなもの
旧文字文化から新画像文化
•
•
•
•
エディターでプログラムを書く
画面に文字が出る.
入力待ちのプロンプトが出る
コマンドを打ち込む
– マシンガンのようにキーボードを
叩く
• 文字・数値で書かれた結果を,即座
に解読する
• 疲れを知らずに際限なく繰り返す
• 沢山の画面,画像が表示される
• キーボートとマウスを使う
• メーセージが頻繁に出てくる.
– 指示されるままにマウスをクリック
する
GUIアプリが出現
• 画像データ量が膨大
• さらに画像処理が複雑化
このプログラムをどう作る?
Object Orient Programming
• 手続き型言語からの転向
– 個別の画像
• Windowの画像データ
個別の物
– 機能的利点
• エラーチェックを個別に行う・強力
• コードとデータをまとめるられる
– 継承
• アプリ・フレームワークを利用
– OOPによる新しい視点
• 問題を容易に概念できる.
• クラスはコードとコードとの防火壁
– 抽象データ型
• Typedef エイリアス(別名)
• ビルトインタイプと同じに使われる
– int,char,など
OOP(ウープ)C++
C から C++ へ
• Smalltalkからobjectの概念
• Cから手続き型言語のsyntax
• 設計上の問題点の解決策
• 配列→構造体→クラス
• 分割コンパイル →
– インターフェース:宣言,ヘッダー・ファ
イル
– フォーカス:変数・関数の適用範囲を
制限
• ライブラリの利用,再利用: 継承
エラーチェックの強化
– でも,領域オーバーは見ないで高速処
理
C記述:手続き型記述
//宣言部
int a,b,c,d;
int .…;
//構造体
struct str1{ int s1; int s2; …}
//手続き記述部
int function f1(int x, int y)
{ int u, v, w, u=x+y; … return w;}
main( ){
int f,g,h;
str1 struct_object;
for(int k=0; …){
if ( a>0) { ….}
}
}
オブジェクト指向設計
• 抽象データタイプ(構造体を強化)
– カプセル化(encapsulation)
• インターフェース記述
– 呼び出し方
• インプリメンテーション
(implementation)
– 関数のコード部分,本体
– プログラムコード+データを外部
から保護
• 非公開(private),
• 公開(public)
• …+ハードウェア(仮想回路,回路)
module
• protected
オブジェクト指向設計
• 継承(inheritance)
– 他のオブジェクトの性質を引継ぐ
階層的な分類
• 拡張可能なプログラム
airplane>airliner>aircraft
• ポリモーフィズム(polymorphism)
多数の形態のギリシャ語
• 一つの名前で多数の動作:汎用ク
ラス
• 関数,演算子のオーバーロード
Shape :: draw( ), erase( )
Circle, square を派生
専用の draw( ), erase( ) を作る
virtual キーワード
二つのC++
• 名前空間 using namespace
– Cからの遺産:分割コンパイル
#include <iostream.h> file名である.
int main{
}
----- new type ----#include <iostream> .h がない
using namespace std;
int main( ){
}
C++の標準入出力
Cでは,print( ),getc( ) 等の関数を使用
C++では入出力の演算子 <<, >>を使用する
#include <iostream>
using namespace std;
int main()
{
int i, j;
double d;
• 標準入出力装置
– cout << expression;
– Cin >> variable;
i = 10;
j = 20;
d = 99.101;
cout << "値を表示: ";
cout << i;
cout << ' ';
cout << j;
cout << ' ';
cout << d;
値を表示: 10 20 99.101
return 0;
}
標準入出力例1
#include <iostream>
using namespace std;
int main()
{
int i, j;
double d;
i = 10;
j = 20;
d = 99.101;
cout << “値を表示: ”;
cout << i << ' ' << j << ' ' << d;
return 0;
}
標準入出力例2
int main()
{
int i;
cout << "値を入力: ";
cin >> i;
cout << “入力した値: ”
<< i << "\n";
return 0;
}
値を入力: 100
入力した値: 100
構造体からクラス
//構造体
struct str1{ int s1; int s2; …}
変数をまとめて名前str1 をつける。
//手続き記述部
int function f1(int x, int y)
{ int u, v, w, u=x+y; … return w;}
関数f1は常にstr1と一緒になって使わ
れる。
一緒にまとめて名前を付けたい。
変数と関数をまとめたものをclassと呼
ぶ
クラス(class)宣言
コメント文
/* abcdefg
#include <iostream>
using namespace std;
class myclass {
// myclassクラス内で非公開
int a;
//
abcdefg
*/
xxxxxx
暗黙のprivate
public:
void set_a (int num);
int get_a();
};
キーワード class
class classA {…}
classA c1, c2, c3;
名前 { 宣言
変数の定義とは違う
int a, b,c;
float x, y, z;
int float 等のtypeの定義と同じ
}
実現部(implementation)
• 宣言はヘッダーファイル(.hpp)に書く
• 実現部はコードファイル(.cpp)に書く
• どれに対応するかを示すのに::を使う
void myclass::set_a (int num)
{
a = num;
}
int myclass::get_a()
{
return a;
}
メンバー関数
member function
Scope operator ::
間違い例
include <iostream>
using namespace std;
int main()
{
myclass ob1, ob2;
ob1.a = 10;
ob2.a = 99;
cout << ob1.get_a() << "\n";
cout << ob2.get_a() << "\n";
return 0;
}
正解
• private 変数は public 関数でし
か参照できない.
int main( )
{
myclass ob1, ob2;
ob1.set_a(10);
ob2.set_a(99);
cout << ob1.get_a() << "\n";
cout << ob2.get_a() << "\n";
return 0;
}
具体例: stack
#include <iostream>
using namespace std;
#define SIZE 10
// 文字を保存するstackクラスを宣言する
class stack {
char stck[SIZE]; // スタック領域を確保する
int tos; // スタック先頭の索引
public:
void init( ); // スタックを初期化する
void push(char ch); // スタックに文字をプッシュする
char pop( ); // スタックから文字をポップする
};
// スタックを初期化する
void stack::init( )
{
tos = 0;
}
stack
// 文字をプッシュする
void stack::push(char ch)
{
if(tos==SIZE) {
cout << "スタックは一杯です";
return;
}
stck[tos] = ch;
tos++;
}
// 文字をポップする
char stack::pop()
{
if(tos==0) {
cout << "スタックは空です";
return 0; // スタックが空の場合はヌルを返す
}
tos--;
return stck[tos];
}
Stackの実行例
int main(){
stack s1, s2; // 2つのスタックを作成する
int i;
// スタックを初期化する
s1.init();
s2.init();
s1.push('a');
s2.push('x');
s1.push('b');
s2.push('y');
s1.push('c');
s2.push('z');
for(i=0; i<3; i++) cout << "s1をポップする: " << s1.pop()
<< "\n";
for(i=0; i<3; i++) cout << "s2をポップする: " << s2.pop()
<< "\n";
return 0;
}
関数のオーバーロード
#include <iostream>
using namespace std;
// myabs()関数を3とおりにオーバーロードする
int myabs(int n);
long myabs(long n);
double myabs(double n);
int main()
{
cout << "-10の絶対値: " << myabs(-10) << "\n\n";
cout << "-10Lの絶対値: " << myabs(-10L) <<
"\n\n";
cout << "-10.01の絶対値: " << myabs(-10.01) <<
"\n\n";
return 0;
}
関数のオーバーロード2
// 整数用のmyabs()関数
int myabs(int n)
{
cout << "整数用のmyabs()\n";
return n<0 ? -n : n;
}
// 長整数用のmyabs()関数
long myabs(long n)
{
cout << "長整数用のmyabs()\n";
return n<0 ? -n : n;
}
// 倍精度浮動小数点数用のmyabs()関数
double myabs(double n)
{
cout << "倍精度浮動小数点数用のmyabs()\n";
return n<0 ? -n : n;
}
システムの処理の流れ
• 全体の処理が大事(仕様設計).
– あらすじを作る.主な出来事を考
える
すなわち,作家である.
• デッサン
– フローチャート
– 構造化プログラミング
– 関数インターフェース
– データも大局的と局所的
プログラムの書き方と関数
プログラム=データの集合と関数の集合
処理の流れ+制御構造
•プログラムの書き方に関数方式がある.
•入出力パラメータと機能
•フローチャート:
処理の流れ(制御)+入出力データ
•SADT:制御フロー,入出力データフロー
//戻り値 関数名
float
triangle
( float width, float height) // パラメーター
{
float area;
area = width * height;
return (area );
}
プログラミングのコツ
• 逐次的な処理の流れ.練習がいる.
• 大まかな処理を分ける.馴れるまで,3つに分ける
ことを繰り返す.
– 入力ー処理ー出力
– 入力1+入力2+入力3
• ・・・・+入力21+入力22+入力33+・・・・
– 処理1+処理2+処理3
– 出力1+出力2+出力3
• 入力と出力を決め,処理は一つにまで砕く
– 入力,出力が扱うデータ(構造)を決める
– 内部処理のデータ(構造)を決める
– 外部に見せるデータと隠蔽するデータを決定.
• 条件は,単なる場合わけ,平易にして,凝らない
• 汎用は難しい,特殊な場合で満足して先に進む
のが肝要.
クラスの作成
• グラフ graph
– ノードの集合
node-1
• ノード node
edge-2
edge-1
– 入力エッジ
– 出力エッジ
• エッジ edge
node-3
node-2
– 接続元ノード
– 接続先ノード
Xcodeを使っての演習
次回の予定: 4/20(金)
1. 関根研の授業のページにEcripsの
使い方がある
2. ホームページから、例題をダウン
ロード
3. 例題でテストをする.
自分のPCはwindowsの場合は、
(1)関根研のホームページから
C++ コンパイラー と
Developer IDEをロードして使用する。
(2)フリーのC++をWebで見つけて使
用。
Turbo C++ explorer
Visual C++ Express など
開発統合環境 IDE
• xcode
• BCC Developper
Visualな画像プログラム?
• フリーでvisual プログラミング?
– VC++やBuilderを購入しなくても
フリーの画像ライブラリがある.
• V ライブラリがある.
• VIDE統合環境もある
V IDE
画像部品ライブラリを使ってプログラム作成
が出来る
V ライブラリを使用した例
C++ builder の例
市販のコンパイラ
フリーのC++ IDE
ボーランド
• Turbo C++ Explore
マイクロソフト
• Visual C++ express
• Webで検索,直ぐ見つかる