2012-02-07 25 views
-1

我正在嘗試在命名空間cop4530內編譯一個新的類模板。你知道我爲什麼回來嗎?這些函數確實存在,並且編譯器對於具體細節沒有多少幫助。我已經做了this thread已經說,但我還是得到了一個未定義符號用g ++編譯類模板 - 未定義符號

g++ -o proj2.x test_list.o 
Undefined symbols for architecture x86_64: 
    "cop4530::List<int>::iterator::operator++(int)", referenced from: 
     _main in test_list.o 
    "cop4530::List<int>::iterator::operator*()", referenced from: 
     _main in test_list.o 
    "cop4530::List<int>::iterator::operator++()", referenced from: 
     _main in test_list.o 
     cop4530::List<int>::List(int, int const&)in test_list.o 
    "cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::iterator::operator++(int)", referenced from: 
     _main in test_list.o 
    "cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::iterator::operator*()", referenced from: 
     _main in test_list.o 
    "cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::iterator::operator++()", referenced from: 
     _main in test_list.o 
     cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::List(int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)in test_list.o 
    "cop4530::List<int>::iterator::iterator(cop4530::List<int>::Node*)", referenced from: 
     cop4530::List<int>::erase(cop4530::List<int>::iterator)in test_list.o 
     cop4530::List<int>::clear() in test_list.o 
     cop4530::List<int>::insert(cop4530::List<int>::iterator, int const&)in test_list.o 
    "cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::iterator::iterator(cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::Node*)", referenced from: 
     cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::erase(cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::iterator)in test_list.o 
     cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::clear()in test_list.o 
     cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(cop4530::List<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::iterator, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)in test_list.o 
ld: symbol(s) not found for architecture x86_64 
collect2: ld returned 1 exit status 
make: *** [List_executable] Error 1 

我的頭被寫了教材,什麼也沒有改變(或可改變此項目),所以這個問題是不存在的。與駕駛員'test_list'一樣。在頭文件的盡頭有一個包括(什麼的問題[它不叫線程,有人告訴我上面說的做)

頁眉反正:

#ifndef DL_LIST_H 
#define DL_LIST_H 
#include <iostream> 

namespace cop4530 { 

template <typename T> 
class List { 
private: 
    // nested Node class 
    struct Node { 
    T data; 
    Node *prev; 
    Node *next; 

    Node(const T & d = T(), Node *p = NULL, Node *n = NULL) 
     : data(d), prev(p), next(n) {} 
    }; 

public: 
    //nested const_iterator class 
    class const_iterator { 
    public: 
    const_iterator(); // default zero parameter constructor 
    const T & operator*() const; // operator*() to return element 

    // increment/decrement operators 
    const_iterator & operator++(); 
    const_iterator operator++(int); 
    const_iterator & operator--(); 
    const_iterator operator--(int); 

    // comparison operators 
    bool operator==(const const_iterator &rhs) const; 
    bool operator!=(const const_iterator &rhs) const; 

    protected: 
    Node *current; // pointer to node in List 
    T & retrieve() const; // retrieve the element refers to 
    const_iterator(Node *p); // protected constructor 

    friend class List<T>; 
    }; 

    // nested iterator class 
    class iterator : public const_iterator { 
    public: 
    iterator() {} 
    T & operator*(); 
    const T & operator*() const; 

    // increment/decrement operators 
    iterator & operator++(); 
    iterator operator++(int); 
    iterator & operator--(); 
    iterator operator--(int); 

    protected: 
    iterator(Node *p); 
    friend class List<T>; 
    }; 

public: 
    // constructor, desctructor, copy constructor 
    List(); // default zero parameter constructor 
    List(const List &rhs); // copy constructor 
    // num elements with value of val 
    explicit List(int num, const T& val = T()); 
    // constructs with elements [start, end) 
    List(const_iterator start, const_iterator end); 

    ~List(); // destructor 

    // assignment operator 
    const List& operator=(const List &rhs); 

    // member functions 
    int size() const; // number of elements 
    bool empty() const; // check if list is empty 
    void clear(); // delete all elements 
    void reverse(); // reverse the order of the elements 

    T &front(); // reference to the first element 
    const T& front() const; 
    T &back(); // reference to the last element 
    const T & back() const; 

    void push_front(const T & val); // insert to the beginning 
    void push_back(const T & val); // insert to the end 
    void pop_front(); // delete first element 
    void pop_back(); // delete last element 

    void remove(const T &val); // remove all elements with value = val 

    // print out all elements. ofc is deliminitor 
    void print(std::ostream& os, char ofc = ' ') const; 

    iterator begin(); // iterator to first element 
    const_iterator begin() const; 
    iterator end(); // end marker iterator 
    const_iterator end() const; 
    iterator insert(iterator itr, const T& val); // insert val ahead of itr 
    iterator erase(iterator itr); // erase one element 
    iterator erase(iterator start, iterator end); // erase [start, end) 


private: 
    int theSize; // number of elements 
    Node *head; // head node 
    Node *tail; // tail node 

    void init(); // initialization 
}; 

// overloading comparison operators 
template <typename T> 
bool operator==(const List<T> & lhs, const List<T> &rhs); 

template <typename T> 
bool operator!=(const List<T> & lhs, const List<T> &rhs); 

// overloading output operator 
template <typename T> 
std::ostream & operator<<(std::ostream &os, const List<T> &l); 

// include the implementation file here 
#include "List.cpp" 

} // end of namespace 4530 

#endif 

這裏是.cpp文件。它沒有完全完成:

using namespace std; 

// --------------------- CONST_ITERATOR --------------------- // 
template <class T> 
List<T>::const_iterator::const_iterator() 
{ // default zero-parameter constructor. Set pointer current to NULL. 
    current = NULL; 
} 

template <class T> 
const T& List<T>::const_iterator::operator*() const 
{ // returns a reference to the corresponding element in the list by calling retrieve() member function. 
    return retrieve(); 
} 

template <class T> 
typename List<T>::const_iterator& List<T>::const_iterator::operator++() 
{ 
    current = current->next; 
    return *this; 
} 
template <class T> 
typename List<T>::const_iterator List<T>::const_iterator::operator++(int) 
{ 
    const_iterator old = *this; 
    ++(*this); 
    return old; 
} 
template <class T> 
typename List<T>::const_iterator& List<T>::const_iterator::operator--() 
{ 
    current = current->prev; 
    return *this; 
} 
template <class T> 
typename List<T>::const_iterator List<T>::const_iterator::operator--(int) 
{ 
    const_iterator old = *this; 
    --(*this); 
    return old; 
} 

template <class T> 
bool List<T>::const_iterator::operator==(const const_iterator &rhs) const 
    {return current == rhs.current;} 

template <class T> 
bool List<T>::const_iterator::operator!=(const const_iterator &rhs) const 
    {return !(*this == rhs);} 

template <class T> 
T& List<T>::const_iterator::retrieve() const 
{ // return a reference to the corresponding element in the list. 
    return current->data; 
} 

template <class T> 
List<T>::const_iterator::const_iterator(Node *p) 
{ // one-parameter constructor 
    // Set pointer current to the given node pointer p. 
    current = p; 
} 

// --------------------- ITERATOR --------------------- // 

template <class T> 
T& List<T>::iterator::operator*() 
{ 
    return retreive(); 
} 

template <class T> 
const T& List<T>::iterator::operator*() const 
{ 
    return retreive(); 
} 

template <class T> 
List<T>::iterator & List<T>::iterator::operator++() 
{ 
    current = current->next; 
    return *this; 
} 

template <class T> 
List<T>::iterator List<T>::iterator::operator++(int) 
{ 
    const_iterator old = *this; 
    ++(*this); 
    return old; 
} 

template <class T> 
List<T>::iterator & List<T>::iterator::operator--() 
{ 
    current = current->prev; 
    return *this; 
} 

template <class T> 
List<T>::iterator List<T>::iterator::operator--(int) 
{ 
    const_iterator old = *this; 
    --(*this); 
    return old; 
} 

template <class T> 
List<T>::iterator::iterator(Node *p) 
{ // one-parameter constructor 
    // Set current to the given node pointer p 
    current = p; 
} 

// --------------------- LIST --------------------- // 

template <class T> 
List<T>::List() 
{ init(); } 

template <class T> 
List<T>::List(const List & rhs) 
{ // Copy constructor 
    init(); 
    *this = rhs; 
} 

template <class T> 
List<T>::List(int num, const T& val) 
{ //Constructs a list with num elements, all initialized with value val 
    init(); 
    iterator itr = begin(); 
    for (int i = 0; i < num; ++i) 
    { 
    insert(itr, val); 
    ++itr; 
    } 
} 

template <class T> 
List<T>::List(const_iterator start, const_iterator end) 
{ // Constructs a List w/ elements from another List between 
    // start and end. [includes start, not end) 
    /////////// 
} 

template <class T> 
List<T>::~List() 
{ // Destructor 
    clear(); 
    delete head; 
    delete tail; 
} 

template <class T> 
const typename List<T>::List& List<T>::operator=(const List &rhs) 
{ // Assignment operator 
    List<T>::iterator ritr = rhs.first(); 
    List<T>::iterator itr = begin(); 

    if(this != &rhs) 
    { 
     clear(); 
     for(; !ritr.isPastEnd(); ritr.advance(), itr.advance()) 
    insert(ritr.retrieve(), itr); 
    } 
    return *this; 
} 

template <class T> 
int List<T>::size() const 
{ // return the number of elements in the List 
    return theSize; 
} 

template <class T> 
bool List<T>::empty() const 
{ // check if list is empty 
    return head->next == NULL; 
} 

template <class T> 
void List<T>::clear() 
{ // delete all elements 
    while(!isEmpty()) 
    erase(begin().retreive()); 
} 

template <class T> 
void List<T>::reverse() 
{ // reverse the order of the elements 
    ///////////// 
} 

template <class T> 
T& List<T>::front() 
{ // reference to the first element 
    return head->next->data; 
} 

template <class T> 
T& List<T>::back() 
{ // reference to the last element 
    return tail->prev->data; 
} 

template <class T> 
void List<T>::push_front(const T & val) 
{ // insert to the beginning 

} 

template <class T> 
void List<T>::push_back(const T & val) 
{ // insert to the end 

} 

template <class T> 
void List<T>::pop_front() 
{ // delete first element 

} 

template <class T> 
void List<T>::pop_back() 
{ // delete last element 

} 

template <class T> 
void List<T>::remove(const T &val) 
{ // remove all elements with value = val 

} 

template <class T> 
void List<T>::print(std::ostream& os, char ofc) const 
{ // print out all elements. ofc is deliminitor 

} 

template <class T> 
typename List<T>::iterator List<T>::begin() 
{ // iterator to first element 
    return List<T>::iterator(head->next); 
} 

template <class T> 
typename List<T>::iterator List<T>::end() 
{ // end marker iterator 
    return List<T>::iterator(tail->prev); 
} 

template <class T> 
typename List<T>::iterator List<T>::insert(iterator itr, const T & x) 
{ 
    Node *p = itr.current; 
    theSize++; 
    return iterator(p->prev = p->prev->next = new Node(x, p->prev, p)); 
} 

template <class T> 
typename List<T>::iterator List<T>::erase(iterator itr) 
{ 
    Node *p = itr.current; 
    iterator retVal(p->next); 
    p->prev->next = p->next; 
    p->next->prev = p->prev; 
    delete p; 
    theSize--; 

    return retVal; 
} 

template <class T> 
typename List<T>::iterator List<T>::erase(iterator start, iterator end) 
{ 
    for(iterator itr = start; itr != end;) 
    itr = erase(itr); 

    return end; 
} 

template <class T> 
void List<T>::init() 
{ // Initaialize the member variables of a List 
    theSize = 0; 
    head = new Node; 
    tail = new Node; 
    head->next = tail; 
    tail->prev = head; 
} 


// --------- OVERLOADS --------- // 

template <typename T> 
bool operator==(const List<T> & lhs, const List<T> &rhs) 
{ 

} 

template <typename T> 
bool operator!=(const List<T> & lhs, const List<T> &rhs) 
{ 

} 

template <typename T> 
std::ostream & operator<<(std::ostream &os, const List<T> &l) 
{ 

} 

讓我只是補充一點,我欣賞任何和所有幫助。我是一名學生,我正在努力學習。

+1

請考慮包括頭部和cop4530 ::名單的定義你的問題 – Gigi 2012-02-07 22:59:34

+0

反正裏面,模板類的方法是在第一次使用實例化,所以當你使用它 – Gigi 2012-02-07 23:05:54

+0

我的列表和列表定義必須是可見水晶球說你錯過了這些方法的定義。然而,它拒絕回答有關爲什麼他們缺少**沒有足夠的信息**的任何問題。如果您沒有向我們展示您的代碼,我們應該如何幫助您? – Grizzly 2012-02-07 23:06:37

回答

2

模板類方法在第一次使用時被實例化,所以List<int>List<string>的定義必須在調用單元中可見。

您的教科書似乎假定編譯器支持外部模板定義,即GCC不支持。

一個簡單的修復方法是在您嘗試修復的編譯單元中複製粘貼List.cpp文件內容。

+0

我在頭文件的末尾加入了一個'#include「List.cpp」',我認爲它們在技術上是一個文件, – jordaninternets 2012-02-07 23:19:34

+0

可以包含頭文件和你也試圖在問題中編譯的文件? – Gigi 2012-02-07 23:25:26

+0

我剛剛添加它。 – jordaninternets 2012-02-07 23:31:34

1

現在你已經貼出你的代碼,答案很簡單(實際上是一樣的一個the question you linked):

的編譯必須看到的模板函數的定義(和模板類的方法)在他們被實例化的點上。因此,不應在.cpp文件中定義模板函數/方法。將它們放在標題中(並在您使用模板的位置包含該標題)。

+0

我無法在頭文件中定義這些。這是作業的一部分。我不允許觸摸頭文件。 – jordaninternets 2012-02-07 23:11:54

+0

你不認爲在你的問題是一個好主意?無論如何,它們需要在它們被使用的地方可見,所以你需要把它們放在一個頭文件中(雖然不一定與它們被聲明的一樣)並且包含那個,或者直接在它們被使用的編譯單元中定義它們(如果只有一個)。所以如果你的家庭作業禁止那些你沒有選擇的東西(如果還有其他的選擇,他們真的不應該被期望在作業中(因爲他們不應該被**)**)。從技術上講,你可以'#include'一個'.cpp'文件,基本上把它當作頭文件來處理,但是爲什麼? – Grizzly 2012-02-07 23:16:27

+0

我在頭文件的末尾包含了一個'#include「List.cpp」'。所以我認爲它被認爲是在該文件中?對? – jordaninternets 2012-02-07 23:20:29

相關問題