2013-03-27 61 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