2015-07-24 2 views
1

Мне был предоставлен некоторый исходный код (как часть задания), который я должен изменить, но я не могу получить немодифицированную версию кода для компиляции, и я разорву свои волосы. (Чтобы быть ясным - этот код предназначен для школьного задания в хэш-таблицах, эти ошибки компиляции не часть задания)ошибка LNK2005 - Что я здесь делаю неправильно?

Я использую визуальную студию 2010 для компиляции. Я работаю над этим весь день и не получаю абсолютно нигде!

Я получаю серию ошибок "LNK2005":

1>------ Build started: Project: Assignment10, Configuration: Debug Win32 ------ 
1> hashmain.cpp 
1>e:\google drive\cpsc 1160\labs\projects\assignment10\assignment10\hashtable.cpp(40): warning C4018: '<' : signed/unsigned mismatch 
1>hashtable.obj : error LNK2005: "public: __thiscall HashTableSavitch::HashTable::HashTable(void)" ([email protected]@@[email protected]) already defined in hashmain.obj 
1>hashtable.obj : error LNK2005: "public: virtual __thiscall HashTableSavitch::HashTable::~HashTable(void)" ([email protected]@@[email protected]) already defined in hashmain.obj 
1>hashtable.obj : error LNK2005: "private: static int __cdecl HashTableSavitch::HashTable::computeHash(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" ([email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) already defined in hashmain.obj 
1>hashtable.obj : error LNK2005: "public: bool __thiscall HashTableSavitch::HashTable::containsString(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)const " ([email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) already defined in hashmain.obj 
1>hashtable.obj : error LNK2005: "public: void __thiscall HashTableSavitch::HashTable::put(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" ([email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) already defined in hashmain.obj 
1>E:\Google Drive\CPSC 1160\Labs\Projects\Assignment10\Debug\Assignment10.exe : fatal error LNK1169: one or more multiply defined symbols found 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

Вот код, я был дан:

hashmain.cpp

// Program to demonstrate use of the HashTable class 

#include <string> 
#include <iostream> 
#include "listtools.cpp" // Your compiler may compile separately 
#include "hashtable.h" 
#include "hashtable.cpp" // Your compiler may compile separately 
using std::string; 
using std::cout; 
using std::endl; 
using HashTableSavitch::HashTable; 

int main() 
{ 
    HashTable h; 

    cout << "Adding dog, cat, turtle, bird" << endl; 
    h.put("dog"); 
    h.put("cat"); 
    h.put("turtle"); 
    h.put("bird"); 
    cout << "Contains dog? " 
     << h.containsString("dog") << endl; 
    cout << "Contains cat? " 
     << h.containsString("cat") << endl; 
    cout << "Contains turtle? " 
     << h.containsString("turtle") << endl; 
    cout << "Contains bird? " 
     << h.containsString("bird") << endl; 

    cout << "Contains fish? " 
     << h.containsString("fish") << endl; 
    cout << "Contains cow? " 
     << h.containsString("cow") << endl; 

    return 0; 
} 

hashtable.h

// This is the header file hashtable.h. This is the interface 
// for the class HashTable, which is a class for a hash table 
// of strings. 

#ifndef HASHTABLE_H 
#define HASHTABLE_H 

#include <string> 
#include "listtools.h" 

using LinkedListSavitch::Node; 
using std::string; 

namespace HashTableSavitch 
{ 
    const int SIZE = 10; 

    class HashTable 
    { 
    public: 
     HashTable(); // Initialize empty hash table 

     // Normally a copy constructor and overloaded assignment 
     // operator would be included. They have been omitted 
     // to save space. 

     virtual ~HashTable(); // Destructor destroys hash table 

     bool containsString(string target) const; 
     // Returns true if target is in the hash table, 
     // false otherwise 

     void put(string s); 
     // Adds a new string to the hash table 

    private: 
     Node<string> *hashArray[SIZE]; 
     static int computeHash(string s); // Compute hash value for string 

    }; // HashTable 
} // HashTableSavitch 
#endif // HASHTABLE_H 

hashtable.cp р

// This is the implementation file hashtble.cpp. 
// This is the implementation of the class HashTable. 

#include <string> 
#include "listtools.h" 
#include "hashtable.h" 

using LinkedListSavitch::Node; 
using LinkedListSavitch::search; 
using LinkedListSavitch::headInsert; 
using std::string; 

namespace HashTableSavitch 
{ 
    HashTable::HashTable() 
    { 
    for (int i = 0; i < SIZE; i++) 
    { 
    hashArray[i] = NULL; 
    } 
    } 

    HashTable::~HashTable() 
    { 
    for (int i=0; i<SIZE; i++) 
    { 
     Node<string> *next = hashArray[i]; 
     while (next != NULL) 
     { 
     Node<string> *discard = next; 
    next = next->getLink(); 
    delete discard; 
     } 
    } 
    } 

    int HashTable::computeHash(string s) 
    { 
    int hash = 0; 
    for (int i = 0; i < s.length(); i++) 
    { 
    hash += s[i]; 
    } 
    return hash % SIZE; 
    } 

    bool HashTable::containsString(string target) const 
    { 
    int hash = this->computeHash(target); 
    Node<string>* result = search(hashArray[hash], target); 
    if (result == NULL) 
     return false; 
    else 
     return true; 
    } 

    void HashTable::put(string s) 
    { 
    int hash = computeHash(s); 
    if (search(hashArray[hash], s)==NULL) 
    { 
     // Only add the target if it's not in the list 
     headInsert(hashArray[hash], s); 
    } 
    } 

} // HashTableSavitch 

listtools.h

//This is the header file listtools.h. This contains type definitions and 
//function declarations for manipulating a linked list to store data of any type T. 
//The linked list is given as a pointer of type Node<T>* which points to the 
//head (first) node of the list. The implementation of the functions are given 
//in the file listtools.cpp. 
#ifndef LISTTOOLS_H 
#define LISTTOOLS_H 

namespace LinkedListSavitch 
{ 
    template<class T> 
    class Node 
    { 
    public: 
     Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink){} 
     Node<T>* getLink() const { return link; } 
     const T& getData() const { return data; } 
     void setData(const T& theData) { data = theData; } 
     void setLink(Node<T>* pointer) { link = pointer; } 
    private: 
     T data; 
     Node<T> *link; 
    }; 

    template<class T> 
    void headInsert(Node<T>*& head, const T& theData); 
    //Precondition: The pointer variable head points to 
    //the head of a linked list. 
    //Postcondition: A new node containing theData 
    //has been added at the head of the linked list. 

    template<class T> 
    void insert(Node<T>* afterMe, const T& theData); 
    //Precondition: afterMe points to a node in a linked list. 
    //Postcondition: A new node containing theData 
    //has been added after the node pointed to by afterMe. 

    template<class T> 
    void deleteNode(Node<T>* before); 
    //Precondition: The pointers before point to nodes that has 
    //at least one node after it in the linked list. 
    //Postcondition: The node after the node pointed to by before 
    //has been removed from the linked list and its storage 
    //returned to the freestore. 

    template<class T> 
    void deleteFirstNode(Node<T>*& head); 
    //Precondition: The pointers head points to the first 
    //node in a linked list; with at least one node. 
    //Postcondition: The node pointed to by head has been removed 
    //for the linked list and its storage returned to the freestore. 

    template<class T> 
    Node<T>* search(Node<T>* head, const T& target); 
    //Precondition: The pointer head points to the head of a linked list. 
    //The pointer variable in the last node is NULL. head (first) node 
    //head (first) node has been defined for type T. 
    //(== is used as the criterion for being equal). 
    //If the list is empty, then head is NULL. 
    //Returns a pointer that points to the first node that 
    //is equal to the target. If no node equals the target, 
    //the function returns NULL. 
}//LinkedListSavitch 

#endif //LISTTOOLS_H 

listtools.cpp

//This is the implementation file listtools.cpp. This file contains 
//function definitions for the functions declared in listtools.h. 

#include <cstddef> 
#include "listtools.h" 

namespace LinkedListSavitch 
{ 
    template<class T> 
    void headInsert(Node<T>*& head, const T& theData) 
    { 
     head = new Node<T>(theData, head); 
    } 

    template<class T> 
    void insert(Node<T>* afterMe, const T& theData) 
    { 
     afterMe->setLink(new Node<T>(theData, afterMe->getLink())); 
    } 

    template<class T> 
    void deleteNode(Node<T>* before) 
    { 
     Node<T> *discard; 
     discard = before->getLink(); 
     before->setLink(discard->getLink()); 
     delete discard; 
    } 

    template<class T> 
    void deleteFirstNode(Node<T>*& head) 
    { 
     Node<T> *discard; 
     discard = head; 
     head = head->getLink(); 
     delete discard; 
    } 

    //Uses cstddef: 
    template<class T> 
    Node<T>* search(Node<T>* head, const T& target) 
    { 
     Node<T>* here = head; 

     if (here == NULL) //if empty list 
     { 
      return NULL; 
     } 
     else 
     { 
      while (here->getData() != target && here->getLink() != NULL) 
       here = here->getLink(); 

      if (here->getData() == target) 
       return here; 
      else 
       return NULL; 
     } 
    } 

}//LinkedListSavitch 

Я думаю, что это выход из моей глубины, я поливаю подобные проблемы/решений здесь и где-нибудь еще, что я мог найти в Google, но я полностью в тупике.

Edit: По просьбе Arcinde, я закомментирована #include "hashtable.cpp" в hashmain.cpp так:

#include <string> 
#include <iostream> 
#include "listtools.cpp" // Your compiler may compile separately 
#include "hashtable.h" 
//#include "hashtable.cpp" // Your compiler may compile separately 
using std::string; 
using std::cout; 
using std::endl; 
using HashTableSavitch::HashTable; 

, который производит следующие ошибки:

1>------ Build started: Project: Assignment10, Configuration: Debug Win32 ------ 
1> hashmain.cpp 
1>hashtable.obj : error LNK2019: unresolved external symbol "class LinkedListSavitch::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > * __cdecl LinkedListSavitch::search<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class LinkedListSavitch::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) referenced in function "public: bool __thiscall HashTableSavitch::HashTable::containsString(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)const " ([email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected][email protected]@@[email protected]@@Z) 
1>hashtable.obj : error LNK2019: unresolved external symbol "void __cdecl LinkedListSavitch::headInsert<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class LinkedListSavitch::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > * &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@YA[email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@[email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) referenced in function "public: void __thiscall HashTableSavitch::HashTable::put(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" ([email protected]@[email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) 
1>E:\Google Drive\CPSC 1160\Labs\Projects\Assignment10\Debug\Assignment10.exe : fatal error LNK1120: 2 unresolved externals 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 
+0

Реализация функции шаблона должна быть видимой в точке создания шаблона. Что по существу означает, что весь код шаблона должен находиться в файле .h. – n0rd

+0

Я раскодировал файлы с расширением .cpp в hashmain.cpp, что значительно изменило выход ошибки. – b1skit

+0

Попробуйте комментировать только '#include" hashtable.cpp "и оставить' #include "listtools.cpp" 'uncommented, который должен исправить его. И скажите тому, кто написал это, что @ n0rd сказал ... это довольно плохо организовано. – Arcinde

ответ

2

Это выглядит как корень ваших проблем заключался в том, что вы создавали шаблонные функции без реализации (ваш .h пытался объявить, и ваш .cpp пытался их определить).

У вас есть два варианта, чтобы решить проблему:

  1. Переместить все от listtools.cpp в listtools.h, таким образом, перемещая оба шаблона экземпляра и реализации в том же месте
  2. Переместить все от listtools. cpp в новый файл (listtoolssupport.h) и удалить объявления из listtools.h.

Используя опцию 1, я переместил все реализации listtools.cpp в listtools.h, используя команды @ n0rd и @ Arcinde. Затем я полностью удалил listtools.cpp, поскольку теперь он ничего не сделал и удалил #includes .cpp.

listtools.ч теперь выглядит следующим образом:

//This is the header file listtools.h. This contains type definitions and 
//function declarations for manipulating a linked list to store data of any type T. 
//The linked list is given as a pointer of type Node<T>* which points to the 
//head (first) node of the list. The implementation of the functions are given 
//in the file listtools.cpp. 
#ifndef LISTTOOLS_H 
#define LISTTOOLS_H 
#include <cstddef> 
namespace LinkedListSavitch 
{ 
template<class T> 
class Node 
{ 
public: 
    Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink) { } 
    Node<T>* getLink() const { return link; } 
    const T& getData() const { return data; } 
    void setData(const T& theData) { data = theData; } 
    void setLink(Node<T>* pointer) { link = pointer; } 
private: 
    T data; 
    Node<T> *link; 
}; 

template<class T> 
void headInsert(Node<T>*& head, const T& theData) 
{ 
    head = new Node<T>(theData, head); 
} 
//Precondition: The pointer variable head points to 
//the head of a linked list. 
//Postcondition: A new node containing theData 
//has been added at the head of the linked list. 

etc etc etc... 

«неразрешенный внешний символ» в основном говорит, что, когда речь идет связать, он не может найти символ узла.

+0

'#include" ListTools.cpp "Я думаю – n0rd

+0

Я раскомментировал файлы .cpp в файле hashmain.cpp и изменил сообщения об ошибках – b1skit

-1

В файле hashmain.cpp

// Program to demonstrate use of the HashTable class 

#include <string> 
#include <iostream> 
//#include "listtools.cpp" // Your compiler may compile separately 
#include "hashtable.h" 
//#include "hashtable.cpp" // Your compiler may compile separately 
using std::string; 
using std::cout; 
using std::endl; 
using HashTableSavitch::HashTable; 

Попробуйте раскомментировать две строки комментариев.

+0

Готово. Я думаю, что я, возможно, прокомментировал их сам, раскомментируя, что они значительно изменили результаты ошибок, поэтому я обновил вопрос. – b1skit

+0

Благодарим вас за это предложение, которое может обеспечить ограниченную немедленную помощь. Правильное объяснение [значительно улучшило бы] (// meta.stackexchange.com/q/114762) его долгосрочную ценность, показав * почему * это хорошее решение проблемы и сделало бы его более полезным для будущих читателей с другие, подобные вопросы. Пожалуйста, отредактируйте свой ответ, чтобы добавить какое-то объяснение, включая сделанные вами предположения. –

-1

Неправильно включить имя файла исходного кода, поэтому вы должны прокомментировать их.

Смежные вопросы