ホーム » 2004 » 6月 » 08

日別アーカイブ: 2004年6月8日

2004年6月
« 5月   7月 »
 12345
6789101112
13141516171819
20212223242526
27282930  

最近の投稿(電子情報)

アーカイブ

カテゴリー

仮想関数

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 の保存処理が無い事、

仮想関数の実装のための補助知識

仮想関数の実装方法の知識として、関数ポインタの説明を行う。