コンテナクラスとテンプレート

例年より情報構造論が早く進んだので、STLとかBoostを少しだけ紹介するために、 その基本のコンテナとテンプレートを紹介する。

コンテナクラス

情報構造論の授業では、リストといった様々なアルゴリズムの説明では、 ひとまず整数でリストを...演習で名前と年齢の構造体で...といった 方式で進めてきたが、リストは次のデータのポインタと、実体のデータと考えれば、 実体データは、整数や名前と年齢といったように、必要に応じて変わってくる。

しかし、アルゴリズムが単純リスト・双方向リスト・2分木と変わっても、 実体データが違うだけで、自分自身で全てを記述することになる。 ただ、複雑なアルゴリズムになればなるほど、この作業が大変になる。

ここで、コンテナクラスという考え方が出てくる。 オブジェクト指向の派生・継承の考え方を使い、例えば単純リストを作りたい場合、 次のポインタだけの基本クラスを作り、そのリストを扱う処理をライブラリとして作っておく。 整数のリスト処理がしたければ、単純リストクラスに、整数を加えた派生クラスを作ったり、 名前と年齢を加えた派生クラスを作れば良い。

// 概念の説明用のクラス宣言であり、
// このままでは使いやすいクラスにはならない
class List {
private:
    List* next ;
public:
    List( List* n ) : next( n ) {}
} ;
class ListInt : public List {
private:
    int data ;
    :
} ;
class ListNameAge : public List {
private:
    char name[20] ;
    int  age ;
    :
} ;

ただ、上記のプログラムでは、小さなオブジェクトでも仮想関数を使ったり、 肝心のアルゴリズムに相当する部分が記述が困難になるので、実際はもう少し 面倒な宣言になってしまう。 このため、C++などではテンプレートクラスがよく利用される。

テンプレート機能

C++でのテンプレート機能とは、型の部分を「仮の型名」としてプログラムを記述し、 そのプログラムを使用する時に具体的な型名を"<>"の中に記載する方式。 コンパイラ的には、異なる型でテンプレートが利用される度に、 その型用の機械語を生成するので、コードが肥大化する可能性があるのが問題ではある。

#include <stdio.h>

template <class T>
class List {
public:
  T data ;
  List<T>* next ;
public:
  List<T>( T x , List<T>*n ) : data( x ) , next( n ) {}
} ;

int main() {
  // 整数型のリスト処理
  List<int>* p = new List<int>( 1 ,
                        new List<int>( 2 , NULL ) ) ;
  for( ; p != NULL ; p = p->next ) {
    printf( "%d\n" , p->data ) ;
  }
  // 実数型のリスト処理
  List<double>*	r = new	List<double>( 1.2 ,
                         new List<double>( 2.3 , NULL ) ) ;
  for( ; r != NULL ; r = r->next ) {
    printf( "%f\n" , r->data ) ;
  }
  return 0 ;
}

このテンプレートクラスの考え方を、究極まで活用したものとして、STL(Standard Template Library)や、 Boostといったライブラリが有名である。

// Cの場合
#include <stdio.h>
int main() {
   int* a ;
   // 配列の作成
   if ( (a = (int*)malloc( sizeof( int ) * 10 )) != NULL ) {
      // 配列の初期化
      for( int i = 0 ; i < 10 ; i++ )
         a[ i ] = i ;

      // 配列の合計
      int sum = 0 ;
      for( int i = 0 ; i < 10 ; i++ )
         sum += a[ i ] ;
      printf( "%d¥n" , sum ) ;
   }
   return 0 ;
}

// STLの場合
#include <numeric>
#include <vector>
#include <list>
using namespace std ;
int main() {
   vector<int> a ; // 配列サイズはSTL任せ...

   for( int i = 0 ; i < 10 ; i++ )
      a.push_back( i ) ; // 配列末尾にiを追加

   int sum = accumulate( a.begin() , a.end() , 0 ) ;
   printf( "%d¥n" , sum ) ;

   // 同じ処理を実数型の単純リストで...
   list<double> b ;
   for( int i = 0 ; i < 10 ; i++ )
      b.push_back( (double)i ) ;
   printf( "%f¥n" , accumulate( b.begin() , b.end() , 0.0 ) ) ;

   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が2014年1月30日 09:31に書いたブログ記事です。

ひとつ前のブログ記事は「優秀学生表彰と学生総会」です。

次のブログ記事は「技科大連携、力覚フィードバック」です。

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