ホーム » スタッフ » 斉藤徹 » 純粋仮想基底クラスと関数ポインタ

2012年5月
« 4月   6月 »
 12345
6789101112
13141516171819
20212223242526
2728293031  

最近の投稿(電子情報)

アーカイブ

カテゴリー

純粋仮想基底クラスと関数ポインタ

先週の仮想関数の説明の応用ということで、 コンテナクラスなどの話につなげるための純粋仮想基底クラスの説明を行う。 その前に、仮想関数の実装の元となっている関数ポインタを簡単に紹介する。

関数ポインタ

関数ポインタとは、名前の通りで、動作説明の簡単なプログラムを紹介。

int add( int x , int y ) { // 加算関数
return x + y ;
}
int mul( int x , int y ) { // 乗算関数
return x * y ;
}
void main() {
int (*f)(int,int) ; // int×2引数、返り値intの関数へのポインタ
f = add ;
printf( "%d" , (*f)( 2 , 3 ) ) ; // 5を表示
f = mul ;
printf( "%d" , (*f)( 2 , 3 ) ) ; // 6を表示
}

関数ポインタを利用すれば、異なるデータに対する処理を、 汎用性高く作ることも可能となる。

int intcmp( int* x , int* y ) { // 整数比較関数
if ( *x > *y )
return 1 ;
else if ( *x < *y )
return -1 ;
else
return 0 ;
}
int vmax( void* array ,    // 配列先頭アドレス
int size ,       // 配列データ件数
int sizeofdata , // 1件あたりのbyte数
int(*f)( void*,void* ) ) { // 比較関数
int i , max = 0 ;
for( i = 0 ; i < size ; i++ )
if ( (*f)( array + max * sizeofdata ,
array + i   * sizeofdata ) )
max = i ;
return max ;
}
int idata[ 4 ] = { 11 , 33 , 22 , 44 } ;
char sdata[ 4 ][ 4 ] = { "ab" , "bc" , "aa" , "c" } ;
void main() {
int m ;
// intcmp関数を使って、idata から最大値を探す
m = vmax( idata , 4 , sizeof(int) , intcmp ) ;
printf( "%d" , idata[ m ] ) ;
// strcmp関数を使って、sdata から最大値を探す
m = vmax( sdata , 4 , sizeof(sdata[0]) , strcmp ) ;
printf( "%s" , sdata[ m ] ) ;
}

純粋仮想基底クラス

これらの仮想基底クラスの考え方をもっと利用すると、 1つの配列に、異なる型の派生クラスを保存することも可能となる。

// 純粋仮想基底クラス
class Object {
public:
virtual void print() = 0 ;
} ;
// 整数クラス
class IntObject : public Object {
private:
int data ;
public:
IntObject( int x ) { data = x ; }
virtual void print() {
printf( "%d" , data ) ;
}
} ;
// 実数クラス
class DoubleObject : public Object {
private:
double data ;
public:
DoubleObject( double x ) { data = x ; }
virtual void print() {
printf( "%f" , data ) ;
}
} ;
// 文字列クラス
class StringObject : public Object {
private:
char* data ;
public:
StringObject( char* x ) { data = x ; }
virtual void print() {
printf( "%s" , data ) ;
}
} ;
void main() {
Object* a[ 3 ] ;
// 配列に整数・実数・文字列が混在できる。
a[0] = new IntObject( 123 ) ;
a[1] = new DoubleObject( 1.23 ) ;
a[2] = new StringObject( "abc" ) ;
// 混在したデータでも、正しく全要素をprint()できる
for( int i = 0 ; i < 3 ; i++ )
a[ i ]->print() ;
}