純粋仮想クラス

先週の仮想関数のより実践的な使い方として、 純粋仮想クラスの使い方を紹介する。

この方法を使えば、新しいデータ構造が必要となっても、 基底クラスから派生させたデータ構造と、 必要最小限の仮想関数の定義だけで、プログラムが書けることを強調する。

C言語を習っただけの学生対象の授業であるため、"using namespace std;" といった文法は一切使わない。

#include <stdio.h>
#include <string.h>

// 純粋仮想基底クラス
//  処理を呼び出すためだけの目的の入れ物クラス
class Object {
public:
  // データを比較するための仮想関数。
  //  単なる入れ物なので、比較する処理を書けない
  virtual int cmp( Object* ) = 0 ;
  // データを表示するための仮想関数
  virtual void print() = 0 ;
} ;

// データの並べ替えをする関数
void sort( Object* array[] , int size )
{
  // 最大選択法
  for( int i = 0 ; i < size - 1 ; i++ ) {
    int m = i ;
    for( int j = i + 1 ; j < size ; j++ ) {
      // array[i]とarray[j]を比較。
      //   array[i]>array[j] なら正の値
      //   = なら0 , < なら負の値 
      int ans = array[m]->cmp( array[j] ) ;

      // より大きい値を見つけたらmに場所を保存
      if ( ans < 0 )
        m = j ;
    }
    // i+1〜最後の範囲の最大(m番目)と先頭を入替え
    Object* tmp = array[ i ] ;
    array[ i ] = array[ m ] ;
    array[ m ] = tmp ;
  }
}

// Objectに整数を追加したデータ
class Integer : public Object {
private:
  int  data ;
public:
  // 整数データのコンストラクタ
  Integer( int x )
    : data( x )
  {}
  // 整数の比較を行う仮想関数を具体的に定義
  virtual int cmp( Object* p ) {
    return data - ((Integer*)p)->data ;
  }
  // データを表示する仮想関数を具体的に定義
  virtual void print() {
    printf( "%d\n" , data ) ;
  }
} ;

// Objectに文字列を追加したデータ
class Cstring : public Object {
private:
  char const*const data ;
public:
  Cstring( char const*const s )
    : data( s )
  {}
  // 整数の比較を行う仮想関数を具体的に定義
  virtual int cmp( Object* p ) {
    return strcmp( ((Cstring*)p)->data , data ) ;
  }
  // データを表示する仮想関数を具体的に定義
  virtual void print() {
    printf( "%s\n" , data ) ;
  }
} ;

int main() {
  // 配列aに72,12,25,6を保存
  Object* a[] = {
    new Integer( 72 ) ,
    new Integer( 12 ) ,
    new Integer( 25 ) ,
    new Integer( 6 )
  } ;
  // データを並び替える
  sort( a , 4 ) ;
  // 並び替えた結果の表示
  for( int i = 0 ; i < 4 ; i++ )
    a[ i ]->print() ;

  // Cstringでも使えることを実験
  Object* b[] = {
    new Cstring( "orange" ) ,
    new Cstring( "grape" ) ,
    new Cstring( "apple" ) ,
    new Cstring( "pine apple" ) ,
    new Cstring( "peach" ) ,
  } ;
  sort( b , 5 ) ;
  for( int i = 0 ; i < 5 ; i++ )
    b[ i ]->print() ;
  return 0 ;
}

C++の文法をちゃんと使おう

比較関数int cmp( Object* ) における、型キャストが説明不足なので、 C言語の基礎知識としてのキャスト演算子の説明(実数整数変換を例とした)を行う。

ただし、C言語の型キャストでの方式は、時代に乗り遅れているので、 このページ上は最近のキャストの使い方を記載しておこう。

最近のC++であれば、以下のような書き方をすべき。

virtual int cmp( Object* p ) {
    Integer* ip = dynamic_cast<Integer*>(p) ;
    if ( ip != NULL )
        return data - p->data ;
    } else {
        return 0 ; // 比較に失敗
    }
}
 

2015年12月

    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

アーカイブ

Google

このブログ記事について

このページは、T-Saitohが2009年6月 4日 11:10に書いたブログ記事です。

ひとつ前のブログ記事は「工場見学旅行の行き先選定中」です。

次のブログ記事は「泡は出ないのかょ…」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。