学プロ - 第 1 回

QueSTudents
Yuto Takei








前回のおさらい
型キャスト
例外処理
ポインタと参照
クラスの詳細
入出力の制御
Demo プロジェクト実装
まとめ
休憩!
前回は次のようなことを扱いました
 変数の定義と使い方
 演算子の種類と動作
 各種ステートメントの働き
 配列の作成と使い方
 オブジェクト指向の基礎
 クラスの実装
 コンストラクタとデストラクタ

数値計算などではオーバー フローが起こる可能
性がある
 オーバー フロー: データ型が扱える値の範囲を演算処
理中に超えてしまうこと

オーバーフローを避けるなどの用途で、ある
データ型の値を別のデータ型の値に変換するこ
とを型キャストという



(type)value
type にはキャスト後の型を指定
double pi = 3.14159265;
int pi2 = (int)pi;
型キャスト


例外とはプログラム中で発生したエラーのこと
不正な処理が起こった場合は、例外を起こすこ
とで、そのことを呼び出し元に通知できる
例外の
 スロー: 不正な処理を通知する
 キャッチ: 例外の事後処理を行う

throw
{
// code that may cause an error
}
catch (type exceptionDetail)
{
// process the error of type
}

try
{
cout << "throwing an exception";
throw 1;
cout << "this won't be executed";
}
catch (int i)
{
cout << "caught exception: " << i;
}

一部の処理ではエラーが発生する
 new 演算子による割り当ての失敗など



そういった処理は try 句の中に入れて、catch
句で例外を捕捉しないと、実行が止まってしま
う
catch(...) という句を作れば、すべてのエ
ラーが捕捉できる
catch 句内で対処できなかったエラーは再ス
ローすることもできる
例外処理



プログラムで扱うデータは、コンピュータのメ
モリ上に格納されている
メモリ上の何番地にあるデータか、というのを
示すのがポインタ
ポインタのアドレス変換機構を自動化したもの
が参照

char* p = "Hello world!";
0x0012ff3c
0x002d1b08
0x48 'H'
0x002d1b09
0x65 'e'
0x0012ff44
0x002d1b0a
0x6c 'l'
0x0012ff48
0x002d1b0b
0x6c 'l'
0x002d1b0c
0x6f 'o'
0x0012ff40
0x002d1b08
⁞





type *ptName = &variable;
type value = *ptName;
間接演算子 * はポインタが指す値を取得する
アドレス演算子 & は変数のアドレスを取得する
オブジェクトを指すポインタを利用して、その
メンバ関数にアクセスするときには、アロー演
算子 -> を利用する

参照とは、関数に渡すパラメータを値渡しでは
なく、参照渡しにすること
 値渡し (pass by value): 変数の中身を渡すこと
 参照渡し (pass by reference): アドレスを渡すこと

関数のパラメータ名の先頭に & を付加
 int f(int &x) { ... }

参照渡しの変数は、値を取得するのに * をつけ
る必要がない
ポインタと参照






フレンド関数
演算子の定義
テンプレート
継承
this ポインタ
static メンバ



メンバ関数ではないが、クラスの private 要素に
もアクセスできる特殊な関数
friend キーワードで修飾
class someClass
{
friend retType funcName(argList);
}

メンバ関数として定義する
 関数名は operator# (# には演算子を指定)
 単項演算子ではパラメータなし、二項演算子では第 2
オペランドをパラメータとして受け取る
 第 1 オペランドは、自分自身になる

フレンド関数として定義する
 関数名はメンバ関数の場合と同様
 すべてのオペランドをパラメータ リストに記述



型パラメータ、ジェネリクスなどともいう
template<class typeVar> キーワードをクラス、
もしくは関数定義の先頭に挿入
型パラメータは、存在する他のクラスの代名詞
として利用することができる
 つまりは型の名前を変数としているということ

あるクラスが、別のクラスの性質を完全に受け
継ぐときに、継承を行うことができる
 継承される側: スーパー クラス (親クラス)
 継承する側: サブ クラス (子クラス)

class subClass : superClass
{
...
}


this という特殊なポインタを利用することで、
自分のクラスを指すことができる
メンバ関数内のみで可能
 フレンド関数や、グローバル関数では利用できない


それぞれのクラスに対して作成されるもの
インスタンスに対してではない
 cf. static でないメンバはインスタンスごとに作成

関数や変数宣言の前に static キーワードを配
置すればよい
クラス実装に関するデモ


IO マニピュレータを利用する
ファイル入出力を行う


#include <iomanip>
IO マニピュレータを利用して、出力書式を指定
 cout << hex << 256;

マニピュレータには次のようなものがある





基数変換: hex, dec, oct
文字配置: left, right
ストリーム幅: setw(int)
充填文字: setfill(char)
指数表記: fixed, scientific


#include <fstream>
データをファイルから読み取ったり、ファイル
に書き込んだりする
 テキスト モード
 バイナリ モード

一般的なファイルの操作としては、
 ファイルを開く (ifstream, ofstream のコンストラクタ)
 読む or 書く (get メソッド, put メソッド)
 ファイルを閉じる (close メソッド)

ifstream fin("fileName", ios::in)
// binary mode: ios::in | ios::binary
if (!fin) // file error occurred
goto fileOpenError;
// read from file...
// get(), read(), getline() etc.
fin.close();

ofstream fout("fileName", ios::out)
// binary mode: ios::out | ios::binary
if (!fout) // file error occurred
goto fileOpenError;
// write to file...
// put(), write() etc.
fout.close();
入出力の制御
第 1 回も含めて、なんでもどうぞ
ヒル暗号の実装
QueSTudents
Hiroyuki Inoue





二次正方行列を定義(数字は4つあることになる)
平文を1バイトずつ区切って、配列につっこむ
暗号に用いる鍵(1~127)を入力
 鍵の行列を作る
平文の行列と鍵の行列をかける
平文(4バイト)と鍵(2バイト)をかけるので暗号文は
平文の2倍 である
平文の行列、鍵の行列をつくる
平文
𝑑0
𝑑1
𝑑3
𝑑4
×n
𝐾
𝐾−1
𝐾+1
𝐾
鍵
暗号化:平文の行列に鍵の行列をかける
𝑑0
𝑑2
𝑑1
𝑑3
𝑑4
𝑑6
𝑑5
𝑑7
0
𝑘
𝑘+1
𝑘−1
𝑘
1
𝑘
𝑘−1
𝑘+1
𝑘
⋮
𝑑4𝑛−4
𝑑4𝑛−2
𝑑4𝑛−3
𝑑4𝑛−1
𝑑4𝑛
𝑑4𝑛+2
𝑑4𝑛+1
𝑑4𝑛+3
𝑛−1
𝑛
𝑘
𝑘−1
𝑘+1
𝑘
𝑘
𝑘−1
𝑘+1
𝑘
暗号文
復号化:平文の行列に鍵の逆行列をかける

汎用関数
private メンバ
ValueType:int型の配列
public メンバ
Matrix:行列を表現
オペレータの定義
*:行列のかけ算の処理
!:逆行列を求める処理
[ ]:添え字の定義
Matrix(ValueType a, ValueType b, ValueType c, ValueType d)
{
data[0] = a; data[1] = b;
data[2] = c; data[3] = d;
}
𝑑0
𝑑1
𝑑3
𝑑4
Matrix<ValueType> operator*(Matrix<ValueType>
{
ValueType
a = data[0] * opd[0] + data[1]
b = data[0] * opd[1] + data[1]
c = data[2] * opd[0] + data[3]
d = data[2] * opd[1] + data[3]
return Matrix(a, b, c, d);
}
𝑑0
𝑑1
opd 0
𝑜𝑝𝑑𝑑1
𝑑3
𝑑4
𝑜𝑝𝑑3
𝑜𝑝𝑑4
opd)
*
*
*
*
opd[2],
opd[3],
opd[2],
opd[3];
Matrix<ValueType> operator!()
{
ValueType
delta = data[0] * data[3] - data[1] * data[2],
a = data[3] / delta,
b = -data[1] / delta,
c = -data[2] / delta,
d = data[0] / delta;
return Matrix(a, b, c, d);
}
𝑑0
1
ad − bc 𝑑3
𝑑1
𝑑4
1. 平文ファイルの指定
2. 暗号後のファイル指定
3. 暗号/復号の指定
4. 鍵の指定
5. 平文ファイルを開く
6. 分割して行列につっこむ
7. 鍵を行列にする
8. 平文行列と鍵行列をかける
9. ファイルに書き込む
istream::peek()
次に読み込まれる1文字を覗く関数
istream::get()
文字を1文字読み取る関数
ostream::put()
文字を書き出す関数
ヒル暗号の実装
デモについて









インライン関数
new, delete 演算子の詳細
オブジェクトのポインタ
コピー コンストラクタ
継承の保護属性、多重継承
仮想クラス
実行時型情報 (RTTI) とキャスト演算子
名前空間
標準テンプレート ライブラリ (STL)





今後もさまざまなセミナーを開催する予定です
9/15: LINQ / ASP.NET セミナー
Microsoft 新宿オフィス Reception Room 15
9/28: Allons en France! (フランスへ行こう!)
文京シビックセンター 26F スカイ ホール
10 月以降については未定
来年 3 月中: 新団体 Launch 合宿
Imagine Cup 2008 France