【问题标题】:Undefined Symbol error in C++ Hashing ProgramC++ 散列程序中的未定义符号错误
【发布时间】:2013-10-08 04:26:51
【问题描述】:

我有一组文件用 makefile 编译来制作一个单独的链式哈希程序。 在我为插入、删除和包含函数添加代码之前,程序一直运行。我直接从书中提取了代码,但是我遇到了一个我无法弄清楚的模棱两可的错误,希望这里有人可以帮助识别它。我没有发布整个程序,因为我有根据的猜测,错误的原因不会在这段代码之外找到(但我可能是错的)

有问题的错误是:

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的include,它又包含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;
}

如果您认为错误出在 makefile 中,这里是 makefile 代码:

#   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 *

【问题讨论】:

  • 你能发布你的myhash()函数的代码吗?看起来您可能正在使用std::hash,在这种情况下您可能只需要#include &lt;functional&gt;,但很难确定。
  • '当我尝试用函数本身编译 .cpp 文件时......'不,那不相关。
  • 您有一个未定义的符号 hash,但您发布的代码中没有使用名为 hash 的符号。因此,从发布的代码来看,这有点神秘。发布更多代码。

标签: c++ templates hash compiler-errors


【解决方案1】:

问题是您已将模板代码放入 cpp 文件中。 All template code should go in header files。否则在使用这些模板时会出现链接错误。

【讨论】:

  • 在我添加插入、删除和包含函数之前,程序中有模板代码(如上面提到的myhash函数),并且编译干净。这仍然是问题吗?
  • 我不知道你的代码的其余部分的结构(从你的问题中并不完全清楚),但是你有一个链接错误,你有一个 cpp 文件中的模板代码,把模板cpp 文件中的代码是导致链接错误的一个众所周知的原因(请参阅上面的链接)。您不应该将模板代码放在 cpp 文件中。解决这个问题,如果仍然有问题,请再次询问。
  • 有时为了解决这个问题,人们所做的是将模板代码放在 cpp 文件中,然后将 cpp 文件#include 到头文件中。当然,同样的事情,模板代码实际上是在头文件中。也许这就是您的其他代码正在发生的事情。
【解决方案2】:

找到了问题,它比我想象的要简单,但约翰的回答是关于模板代码在哪里有帮助。

原来我需要让我的哈希函数(不是 myhash)成为一个非模板类,并让它接受一个字符串变量。在查看原型后,这对我来说很明显:

int hash(const string &key);

我只是在最初创建定义时假设它将是一个模板类,就像其他所有东西一样!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-08
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多