0

関数ポインタの非常に基本的なハッシュマップを作成する必要があります。私の要件は、それに値を追加し、キーに基づいて取得することです。政治的な理由で、私は標準的なライブラリを使用できません。正常に動作するコードがあります。しかし、クラスメンバー関数への関数ポインターが必要な場合、これは機能しません。以下のコードの変更はどうあるべきかについての提案。

このPINGとREFRESHは独立した機能です。したがって、このコードは機能します。しかし、これらの関数をHashMapクラスに移動すると、失敗します。

コード: -

#include <iostream> 
#include <cstdlib> 
#include <cstring> 
#include <iomanip> 
using namespace std; 
typedef void (*FunctionPtr)(); 

    void ping(){
    cout<<"ping";
}
void refresh(){
    cout<<"refresh";
}

class HashEntry {
private:
    int key;
    FunctionPtr func_ptr1;;
public:
    HashEntry(int key, FunctionPtr fptr) {
        this->key = key;
        this->func_ptr1 = fptr;
    }
    int getKey() {
        return key;
    }
    FunctionPtr getValue() {    
        return this->func_ptr1;
    }
};

const int TABLE_SIZE = 128;
class HashMap {
private:
        HashEntry **table;
public:
        HashMap() {
            table = new HashEntry*[TABLE_SIZE];
            for (int i = 0; i < TABLE_SIZE; i++)
                  table[i] = NULL;
      }

      FunctionPtr get(int key) {
            int hash = (key % TABLE_SIZE);
            while (table[hash] != NULL && table[hash]->getKey() != key)
                  hash = (hash + 1) % TABLE_SIZE;
            if (table[hash] == NULL)
                  return NULL;
            else
                  return table[hash]->getValue();
      }

      void put(int key, FunctionPtr fptr) {
            int hash = (key % TABLE_SIZE);
            while (table[hash] != NULL && table[hash]->getKey() != key)
                  hash = (hash + 1) % TABLE_SIZE;
            if (table[hash] != NULL)
                  delete table[hash];
            table[hash] = new HashEntry(key, fptr);
      }     

      ~HashMap() {
            for (int i = 0; i < TABLE_SIZE; i++)
                  if (table[i] != NULL)
                        delete table[i];
            delete[] table;
      }
};


void main(){
    HashMap* pHashsMap = new HashMap();
    pHashsMap->put(1,ping);
    pHashsMap->put(2,refresh);
    pHashsMap->put(3,ping);
    pHashsMap->put(4,refresh);
    pHashsMap->put(5,ping);
    pHashsMap->put(6,refresh);

    cout<<" Key 1---"<<pHashsMap->get(1)<<endl;
    pHashsMap->get(1)();
    cout<<" Key 5---"<<pHashsMap->get(5)<<endl;
    pHashsMap->get(5)();
    cout<<" Key 3---"<<pHashsMap->get(3)<<endl;
    pHashsMap->get(3)();
    cout<<" Key 6---"<<pHashsMap->get(6)<<endl;
    pHashsMap->get(6)();

    delete pHashsMap;
}
4

1 に答える 1

1

賢いアレックの答え: のコードを調べて、std::bindそこから学び、独自のコードを作成します (ただし、STL/boost を使用しないのは賢明ではありません...)。

より簡単な答え: 通常の関数ポインターとクラス メンバー関数ポインターを保持する共用体型を作成し、それがクラス ポインターであるかどうかを示す bool を格納する必要があります。

class funcbind_t
{
    union
    {
        void (*pf)();
        void (SomeClass::*mfp)();
    };

    bool member;

    funcbind_t(void (*_pf)()) : pf(_pf), member(false)
    {
    }

    funcbind_t(void (SomeClass::*_mpf)()) : mpf(_mpf), member(true)
    {
    }

    void operator ()()
    {
        if(member)
            mfp();
        else
            fp();
    }
};

ご覧のとおり、関数に異なるパラメーターが必要になると、これは面倒になります。

于 2012-09-28T15:50:49.790 に答える