qsortに渡す関数ポインタにクラスのメンバ関数を渡したい


目次に戻る


掲示板に「C++のクラスで宣言したメソッドを使ってqsortできないか?」という質問があっ たのでお答えします。
基本的に無理です
「しょ、しょんな〜〜」というような解答が来そうですが、事実です。
そもそも、qsortはC言語用のライブラリ(関数集)であって、C++用ではないのです 。C++は(厳密には違うけど)C言語の上位互換なので、事実qsortを利用する事はでき ますが、しょせんはC言語用ライブラリ。C++でソート等を行いたいのであればSTLを利 用しましょう。
 
ただ、それでは解答にならないので強引に無理矢理利用する方法を紹介します。下 の例は、qsortに渡す比較関数にクラスのメンバ関数を渡している例です。
TMyClassという名前のクラスのメンバ関数「CompareFunction」がqsortに渡す比較 関数になります。この関数、宣言を見るとstaticとして宣言されています。
このように比較関数をstatic宣言すれば、引数に「関数のポインタ」が必要な関数をC ++のクラスから利用する事ができるのです。
 
 
#include <stdio.h>
#include <stdlib.h>

// -------------------------------------------------------------
// TMyClass クラスの宣言
class TMyClass
{
 int FData;
public:
 void SetData( int value );
 int GetData( void );

 // 比較関数 static宣言されている事に注意。
 static int CompareFunction( const void *a , const void *b );
};

// -------------------------------------------------------------
// TMyClass メンバ SetData
void TMyClass::SetData( int value )
{
 FData = value;
}

// -------------------------------------------------------------
// TMyClass メンバ GetData
int TMyClass::GetData( void )
{
 return FData;
}

// -------------------------------------------------------------
// TMyClass メンバ CompareFunction
int TMyClass::CompareFunction( const void *a , const void *b )
{
 const TMyClass *ma = (TMyClass*)a;
 const TMyClass *mb = (TMyClass*)b;

 if( ma->FData < mb->FData ){
  return -1;
 } else if( ma->FData == mb->FData ){
  return 0;
 } else {
  return 1;
 }
}
 

int main()
{
 TMyClass data[10];

 // 乱数を使用して、配列を初期化する。
 for( int i=0 ; i<sizeof( data ) / sizeof(data[0]) ; i++ ){
  data[i].SetData( rand() );
  printf("%d ",data[i].GetData());
 }
 printf("\n");

 // ソート開始
 qsort( data , sizeof(data)/sizeof(data[0]) , sizeof(data[0]) , TMyClass::CompareFunction );
 /* 次のように書いてもOK
 qsort( data , sizeof(data)/sizeof(data[0]) , sizeof(data[0]) , data[0].CompareFunction );
 */

 // 結果表示
 for( int i=0 ; i<sizeof( data ) / sizeof(data[0]) ; i++ ){
  printf("%d ",data[i].GetData());
 }
 printf("\n");

 return 0;
}



目次に戻る