仮想関数
6/7(Mon)は、Happy Monday 法の逆の余波により、火曜日の授業に振り替え。 おかげで、6/7,8の連日でオブジェクト指向の授業。 このため講義メモは 2 日分を一括記載。
共用体による異なるデータを1つの配列に保存するプログラム例
導出の概念を簡単に復習し、導出の便利な使い方の一例ということで、 コンテナクラスの概念を説明。コンテナクラス側で、データを扱う 一般的な処理を作成しておき、コンテナクラスを使う時は、自分用 のデータを追加した導出クラスを作成し、継承概念を利用し、 あらかじめ作られているアルゴリズムを使うという説明を行う。
仮想関数の説明として、基底クラスを作成し、導出したクラスで 異なる処理を呼び出すという概念を述べる。しかしこれだけでは、 判りにくいので、C言語による共用体の使い方を説明し、 別に仮想関数の話しをすることにする。
union A { int x ; float y ; char z[ 10 ] ; } ; struct AA { int type ; union A data ; } ; void set_int( struct AA*p , int d ) { p->type = 1 ; p->data.x = d ; } void set_float( struct AA*p , float d ) { p->type = 2 ; p->data.y = d ; } void print( struct AA*p ) { if ( p->type == 1 ) // ディスパッチ処理が羅列される例 printf( "%d\n" , p->data.x ) ; else if ( p->type == 2 ) printf( "%f\n" , p->data.y ) ; } void main() { struct AA a[ 2 ] ; set_int( &a[ 0 ] , 1234 ) ; // a[] に異なるデータが保存できる例 set_float( &a[ 1 ] , 1.234 ) ; for( int i = 0 ; i < 2 ; i++ ) // 異なるデータにメソッドは同じだけど print( &a[ i ] ) ; // 異なる処理が実行されるという説明 }
仮想関数のプログラムの実例
仮想関数の最も簡単な実例として、以下のプログラムを提示する。
// 1行記述が多いのは、シンプル日記の都合上。 class Data { public: virtual void print() = 0 ; // virtual は仮想関数を表すキーワード // =0 は、基底クラスでのメソッドが無いことを表す } ; class DataInt : public Data { private: int x ; public: void set( int d ) { x = d ; } virtual void print() { printf( "%d" , x ) ; } } ; class DataFloat: public Data { private: float y ; public: void set( float d ) { y = d ; } virtual void print() { printf( "%f" , y ) ; } } ; void main() { DataInt b ; b.set( 1234 ) ; DataFloat c ; c.set( 1.234 ) ; Data* a[ 2 ] ; a[0] = &b ; // 派生クラスポインタは基底クラスポインタに型変換可能 a[1] = &c ; for( int i = 0 ; i < 2 ; i++ ) a[ i ]->print() ; // 仮想関数の呼び出し }
仮想関数と union での事例の比較として、次の点を強調する。
- if文ディスパッチャが無くなっている事、
- 型識別ID の保存処理が無い事、
仮想関数の実装のための補助知識
仮想関数の実装方法の知識として、関数ポインタの説明を行う。