0

別の連鎖ハッシュ プログラムを作成するために、makefile でコンパイルする一連のファイルがあります。insert、remove、contains functions のコードを追加するまで、プログラムは機能します。私は本からコードをそのまま引き出しましたが、理解できないあいまいなエラーが発生し、ここの誰かがそれを特定するのを手伝ってくれることを望んでいます. エラーの原因はこのコードの外では見つからないという知識に基づいた推測を行っているため、プログラム全体を投稿しませんでした (ただし、間違っている可能性があります)。

問題のエラーは次のとおりです。

Undefined                       first referenced
 symbol                             in file
hash(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)hashApp.o

また、これが関連しているかどうかはわかりませんが、.cpp ファイルを関数だけでコンパイルしようとすると、次のようになります。

Undefined                       first referenced
 symbol                             in file
main                                /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crt1.o
ld: fatal: Symbol referencing errors. No output written to a.out
collect2: ld returned 1 exit status

関数は次のとおりです。文字列はリストのベクトルでハッシュされます。

template <class HashObj>
bool HashTable<HashObj>::contains(HashObj &item)
{
  const list<HashObj> & whichList = theLists[ myhash( item ) ];
  return find( whichList.begin( ), whichList.end( ), item ) != whichList.end( );    
}        

template <class HashObj>
bool HashTable<HashObj>::insert(const HashObj &item)
{
    list<HashObj> & whichList = theLists[ myhash( item ) ];
    if( find( whichList.begin( ), whichList.end( ), item ) != whichList.end( ) )
        return false;
    whichList.push_back( item );
    return true; 
} 

template <class HashObj>
bool HashTable<HashObj>::remove(const HashObj &item)
{
  list<HashObj> & whichList = theLists[ myhash( item ) ];
  typename list<HashObj>::iterator itr = find( whichList.begin( ), whichList.end(), item );

  if( itr == whichList.end( ) )
  return false;

  whichList.erase(itr);
  return true;
 } 

これは、同じファイルの myhash 関数です。

 template <class HashObj>
int HashTable<HashObj>::myhash(const HashObj &item) const
{
    int hashVal = hash(item);

    hashVal %= theLists.size();
    if (hashVal < 0)
        hashVal += theLists.size();

    return hashVal;
}

上記の .cpp コードには、hashTable.h のインクルードがあり、hashPrototypes.h がインクルードされます。

hashPrototypes.h には

int hash(int key);
int hash(const string &key);

私のハッシュ関数は、入力内容に基づいて実行可能ファイルを作成するメイクファイルからコンパイルされます。たとえば、hash1.cpp を使用しているので、make HASH=hash1 と入力すると、それらがすべてまとめてコンパイルされます。

ここに私の hash1.cpp コードがあります:

#include "hashTable.h"
#include <cmath>
#include <cstdlib>
using namespace std;

template <class HashObj>
int hash(const HashObj &item)
    {
    int hashVal = 0;

    for( int i = 0; i < item.length( ); i++ )
        hashVal = 37 * hashVal + item[ i ];

    return hashVal;
}

エラーがメイクファイルにあると思われる場合は、メイクファイルのコードを次に示します。

#   Make file for hashing
#   Executable for the program will be in: hashTest

#default function is looked for in hashS1
#to give it another function make=filename without the suffix
HASH = hashS1

$(HASH)Test:  $(HASH).o hashTable.o hashApp.o
    g++ -o $(HASH)Test $(HASH).o hashTable.o hashApp.o

hashApp.o:      hashTable.h hashPrototypes.h hashApp.cpp hashTable.cpp
    g++ -c hashApp.cpp

hashTable.o:    hashTable.h hashTable.cpp $(HASH).cpp
g++ -c hashTable.cpp

$(HASH).o:  hashPrototypes.h $(HASH).cpp
g++ -c $(HASH).cpp

clean:
rm -f *.o 
touch *
4

2 に答える 2

3

問題は、テンプレート コードを cpp ファイルに入れたことです。すべてのテンプレート コードはヘッダー ファイルに入れる必要があります。そうしないと、これらのテンプレートを使用するときにリンク エラーが発生します。

于 2013-10-08T04:55:06.490 に答える
0

問題が見つかりました。思ったより簡単でしたが、テンプレートコードがどこに役立ったかに関するジョンの答えです。

ハッシュ関数 (myhash ではない) を非テンプレート クラスにして、文字列変数を取る必要があることがわかりました。これは、プロトタイプを見た後、私には明らかです。

int hash(const string &key);

定義を最初に作成したとき、それは他のすべてと同様にテンプレート化されたクラスになると思いました!

于 2013-10-08T14:14:32.067 に答える