2013-03-27 63 views
0

我知道那裏有很多類似的問題 - 相信我,我已經閱讀過它們 - 但我無法得到它的工作。這是特別的,因爲我前幾天解決了與相關計劃的類似鬥爭。我意識到對我的問題的回答很有可能是在那裏,但我花了好幾個小時或兩個看,沒有太多的成功。C++鏈接錯誤的模板,只使用頭文件,爲什麼?

我想建立一個鏈表。該程序由四個文件組成 - 鏈接列表和節點的頭文件,以及列表中的一個interace,以及包含main方法的.cpp文件。

ListTester.cpp

#include "StdAfx.h" 
#include "LinkedList.h" 
#include <iostream> 
#include <string> 

using namespace std; 

template <typename T> 
void main() { 

    LinkedList<int> a; 
    a.addFirst(22); 
    a.addFirst(24); 
    a.addFirst(28); 
    LinkedList<int> b; 
    b = a; 
    b = b + a; 
    b += a; 

    cout<<b; 
} 

LinkedList.h

#ifndef LINKEDLIST_H 
#define LINKEDLIST_H 
#include "Node.h" 
#include "List.h" 
#include <ostream> 

template <typename T> 

class LinkedList : public List { 

private: 

    int n; 
    Node<T> *first; 
    Node<T> *last; 

public: 

    LinkedList(); 
    LinkedList(const LinkedList & ll); 
    ~LinkedList(); 
    int size(); 
    void clear(); 
    void addFirst(T data); 
    void addLast(T data); 
    T removeFirst(); 
    T removeLast(); 
    T getFirst(); 
    T getLast(); 
    Node<T>* getFirstNode() const; 
    void addAt(int pos, T data); 
    T removeAt(int pos); 
    T getAt(int pos); 
    LinkedList& operator=(const LinkedList<T> &right); 
    T operator[](int i); 
    LinkedList& operator+(const LinkedList<T> &right); 
    LinkedList& operator+=(const LinkedList<T> &right); 
    friend std::ostream& operator<<(std::ostream &os, const LinkedList<T> & ll); 

}; 

template <typename T> 
LinkedList<T>::LinkedList() { 
     this->n = 0; 
     this->first = 0; 
     this->last = 0; 
    } 

template <typename T> 
LinkedList<T>::LinkedList(const LinkedList & ll) { 
    this-> n = 0; 
    this-> first = 0; 
    this-> last = 0; 

    Node *temp = ll.first; 

    while(temp) { 
     addLast(temp->getData()); 
     temp = temp->getNext(); 
    } 

} 

template <typename T> 
void LinkedList<T>::addFirst(T data) { 
    Node *p = new Node(data, first); 
    first = p; 
    if(!n) 
     last = p; 
    n++; 
} 

template <typename T> 
void LinkedList<T>::addLast(T data) { 
    Node *p = new Node(data, 0); 
    if(!n) 
     first = last = p; 
    else { 
     last->next = p; 
     last = p; 
    } 
    n++; 
} 

template <typename T> 
T LinkedList<T>::removeFirst() { 
    T a = 0; 
    if(!n) 
     throw "Can't retrieve element from empty list!"; 
    a = first->getData(); 
    Node *p = first->next; 
    delete first; 
    first = p; 
    n--; 
    return a; 
} 

template <typename T> 
T LinkedList<T>::removeLast() { 
    T a = 0; 
    if(!n) 
     throw "Can't retrieve element from empty list!"; 
    if(n == 1) { 
     a = last->getData(); 
     delete first; 
     first = last = 0; 
    } 
    else { 
     a = last->getData(); 
     Node *p = first; 
     while(p->next->next != 0) 
      p = p->next; 
     delete p->next; 
     p->next = 0; 
     last = p; 
    } 
    n--; 
    return a; 
} 

template <typename T> 
T LinkedList<T>::getFirst() { 
    if(n < 1) 
     throw "Can't retrieve element from empty list!"; 
    return first->getData(); 
} 

template <typename T> 
T LinkedList<T>::getLast() { 
    if(n < 1) 
     throw "Can't retrieve element from empty list!"; 
    return last->getData(); 
} 

template <typename T> 
Node<T>* LinkedList<T>::getFirstNode() const { 
    return first; 
} 

template <typename T> 
int LinkedList<T>::size() { 
    return n; 
} 

template <typename T> 
T LinkedList<T>::getAt(int pos) { 
    if(pos >= n) 
     throw "Element index out of bounds!";  
    Node *temp = first; 
    while(pos > 0) { 
     temp = temp->next; 
     pos--; 
    } 
    return temp->getData();  
} 

template <typename T> 
void LinkedList<T>::clear() { 
    Node *current = first; 
    while(current) { 
     Node *next = current->next; 
     delete current; 
     if(next) 
      current = next; 
     else 
      current = 0; 
    } 
} 

template <typename T> 
void LinkedList<T>::addAt(int pos, T data) { 
    if(pos >= n) 
     throw "Element index out of bounds!";  
    if(pos == 0) 
     addFirst(data); 
    else { 
     Node *temp = first; 
     while(pos > 1) { 
      temp = temp->next; 
      pos--; 
     } 
     Node *p = new Node(data, temp->next); 
     temp-> next = p; 
     n++; 
    } 
} 

template <typename T> 
T LinkedList<T>::removeAt(int pos) { 
    if(pos >= n) 
     throw "Element index out of bounds!";  
    if(pos == 0) 
     return removeFirst(); 
    if(pos == n - 1) 
     return removeLast(); 
    else { 
     Node *p = first; 
     while(pos > 1) { 
      p = p->next; 
      pos--; 
     } 
     T a = p->next->getData(); 
     Node *temp = p->next; 
     p->next = p->next->next; 
     delete temp; 
     n--; 
     return a; 
    }  
} 

template <typename T> 
LinkedList<T>::~LinkedList() { 
    clear(); 
} 

template <typename T> 
LinkedList<T>& LinkedList<T>::operator=(const LinkedList<T> &right) { 
    if(this != &right) { 

     n = 0; 
     first = 0; 
     last = 0; 

     Node *temp = right.first; 
     while(temp) { 
      addLast(temp->getData()); 
      temp = temp->getNext(); 
     }   
    } 
    return *this; 
} 

template <typename T> 
T LinkedList<T>::operator[](int i) { 
    return getAt(i); 
} 

template <typename T> 
LinkedList<T>& LinkedList<T>::operator+(const LinkedList<T> &right) { 
    Node *temp = right.first; 
    while(temp) { 
     addLast(temp->getData()); 
     temp = temp->getNext(); 
    } 
    return *this; 
} 

template <typename T> 
LinkedList<T>& LinkedList<T>::operator+=(const LinkedList<T> &right) { 
    Node *temp = right.first; 
    while(temp) { 
     addLast(temp->getData()); 
     temp = temp->getNext(); 
    } 
    return *this; 
} 

template <typename T> 
std::ostream& operator<<(std::ostream &os, const LinkedList<T> &ll) { 
    Node *temp = ll.getFirstNode(); 
    while(temp) { 
     os<<temp->getData()<<std::endl; 
     temp = temp->getNext(); 
    } 
    return os; 
} 

#endif 

Node.h

#ifndef NODE_H 
#define NODE_H 

template <typename T> 
class Node { 

private: 

    T data; 

public: 

    Node<T>* next; 
    T getData(); 
    Node<T>* getNext(); 
    Node(T data, Node<T>* next); 
    Node(const Node & n); 

}; 

template <typename T> 
T Node<T>::getData() { 
     return data; 
    } 

template <typename T> 
Node<T>* Node<T>::getNext() { 
    return next; 
} 

template <typename T> 
Node<T>::Node(T data, Node<T>* next) { 
    this->data = data; 
    this->next = next; 
    } 

template <typename T> 
Node<T>::Node(const Node & n) { 
    data = n.data; 
    next = n.next; 
} 

#endif 

List.h

#ifndef LIST_H 
#define LIST_H 

class List 
    { 

public: 

    virtual void addFirst(int data) = 0; 
    virtual void addAt(int pos, int data) = 0; 
    virtual void addLast(int data) = 0; 
    virtual int getFirst()= 0; 
    virtual int getAt(int pos) = 0; 
    virtual int getLast()= 0; 
    virtual int removeFirst()= 0; 
    virtual int removeAt(int pos) = 0; 
    virtual int removeLast()= 0; 
    virtual int size() = 0; 
    virtual void clear() = 0; 
    virtual ~List() {};  

    }; 

#endif 

爲此,我得到LNK2019和LNK1120鏈接錯誤。我知道我在分離的.h和.cpp文件中實現Queue時習慣這樣做。但是通過在標題中做所有事情來解決它。我也知道這可能發生在沒有實現一個命名方法的時候,但我在這裏找不到這些。那麼這是什麼原因造成的?我希望編譯器/ IDE能指出我錯誤的可能原因。但是再次,如果找到錯誤的線路是一件容易的事情,我認爲它已經做到了。 VS 2012 btw。

+0

它會幫助我們查看錯誤。 – 2013-03-27 13:07:44

+1

推測,鏈接器會告訴你哪些符號未解析。這應該指向你(或者我們,如果你告訴我們它們是什麼)的錯誤原因。 – 2013-03-27 13:08:41

+0

* real *錯誤,不僅僅是LNK2019和LNK1120,這對Linux用戶也沒有任何意義。 – 2013-03-27 13:08:43

回答

2
// template <typename T> 
void main() { 

    LinkedList<int> a; 
    a.addFirst(22); 
    a.addFirst(24); 
    a.addFirst(28); 
    LinkedList<int> b; 
    b = a; 
    b = b + a; 
    b += a; 

    cout<<b; 
} 

你需要一個主功能,而不是一個主要函數模板。這可能是鏈接器錯誤的來源:沒有稱爲「main」的函數。

這將不起作用的原因主要是因爲除非使用類模板和函數模板,否則它們不會擴展爲真正的代碼。由於main是程序的入口點,因此不會在任何地方調用main,因此不會生成main的代碼。此外,由於C++編譯器對函數(處理重載,模板,命名空間等)所做的名稱改變,將在生成的此主模板的程序集中生成的符號可能不會是正確的。如果它正在尋找一個符號'主',它看到

$__T_float_main_blah_blah_blah 

那麼你不會連接反正。長話短說:main是一個函數,而不是函數模板。

+0

謝謝。我必須承認,即使我明白模板是什麼,我仍然不完全理解C++模板語法。我已經評論了你建議的這一行,並且修復了LinkedList.h文件中沒有後綴的大量引用。現在我得到這個: – 2013-03-27 13:20:03

+0

錯誤錯誤LNK2019:無法解析的外部符號「class std :: basic_ostream >&__cdecl operator <<(class std :: basic_ostream >&class LinkedList const&)「(?? 6 @ YAAAV?$ basic_ostream @ DU?$ char_traits @ D @ std @@@ std @@ AAV01 @ ABV?$ LinkedList @ H @@@ Z)在函數引用_main \t C:\用戶\質樸MF \ CPP \鏈表\鏈表\ ListTester.obj \t鏈表 錯誤\t \t 2錯誤LNK1120:1周無法解析的外部\t C:\用戶\質樸MF \ CPP \鏈表\調試\ LinkedList.exe LinkedList – 2013-03-27 13:20:26

+0

這可能意味着你對於鏈接列表類型,不要有operator <<的重載。 – bstamour 2013-03-27 13:22:27

2

您爲main創建了函數模板。這不僅沒有意義(內部沒有提及模板參數),它也從來沒有實例化過(即使它是,它可能不會解析到程序需要作爲起點的正確main)。

此外,它應該是int main而不是void main