2013-02-16 65 views
1

我總是C++未定義的參考模板類方法

未定義的參考`圖:: InsertVertex(的std :: string)」

如果我編譯我的項目!任何暗示爲什麼他不能解決這個參考? (所有文件都在NetBeans項目文件夾)

// 的main.cpp

#include <cstdlib> 
#include <string> 
#include "Graph.h" 

using namespace std; 

int main(int argc, char** argv) 
{ 
    Graph<string> *graph = new Graph<string>(); // <--- ERROR 

    graph->InsertVertex("A"); 

    return 0; 
} 

// Node.h

#include <iostream> 
#include "Graph.h" 

template<class T> 
class Node 
{ 

friend class Graph;  

public: 
    Node(T val) 
    { 
     this->data = val; 
     this->vertList = NULL; 
     this->next = NULL; 
    } 

    Node(const Node& orig); 
    virtual ~Node(); 

private: 
    T data; 
    Node<T> *vertList; 
    Node<T> *next; 
    int status; 

}; 

// Graph.h

#include <iostream> 
#include "Node.h" 

template <class T> 
class Graph 
{  
public: 
    Graph() 
    { 
     head = NULL;   
    } 

    void InsertVertex(T val);  
    void InsertEdge(T v_val, T e_val); 

    void PrintVertices(); 
    void PrintEdges(T v_val); 

    void DeleteEdge(T v_val, T e_val); 
    void DeleteVertex(T val); 

    void bfs();  

private: 
    Node<T> *head; 

}; 

// Graph.cpp

#include "Graph.h" 

template <class T> 
void Graph<T>::InsertVertex(T val) 
{ 
    Node<T> *temp = new Node<T>(val); 

    if(head == NULL) head = temp; 
    else 
    { 
     Node<T> node = head; 

     while(node->vertList != NULL) 
      node = node->vertList; 

     node->vertList = temp; 
    } 
} 

template <class T> 
void Graph<T>::InsertEdge(T v_val, T e_val) 
{ 
    if (head != NULL) 
    { 
     Node<T> *k = head; 
     Node<T> *t = head; 
     Node<T> *temp = new Node<T> (e_val);   

     while (t != NULL) 
     { 
      if (t->data == v_val) 
      { 
       Node<T> *s = t; 

       while (s->next != NULL) 
        s = s->next; 

       s->next = temp; 

       while (k != NULL) 
       { 
        if(k->data == e_val) break; 

        k = k->vertList; 
       } 

       temp->vertList = k; 
       return; 
      } 

      t = t->vertList; 
     } // end while loop   
    } 
    else std::cout << "Add first vertices to the graph" << std::endl; 
} 

template <class T> 
void Graph<T>::PrintEdges(T v_val) 
{ 
    Node<T>* t = head; 

    while (t != NULL) 
    { 
     if (t->data == v_val) 
     { 
      while (t->next != NULL) 
      { 
       std::cout << t->next->vertList->data << " "; 
       t = t->next; 
      } 
     } 
     t = t->vertList; 
    } 
} 

template <class T> 
void Graph<T>::PrintVertices() 
{ 
    Node<T>* t = head; 

    while (t != NULL) 
    { 
     std::cout << t->data << " "; 
     t = t->vertList; 
    } 
} 
+5

不能將類模板的成員函數定義放在'.cpp'文件中。 – 2013-02-16 19:19:07

+2

本週至少有五次這樣問。你應該認真改善你的搜索結果。 :p – 2013-02-16 19:20:51

+0

搜索自己的問題標題[「C++未定義的模板類方法參考」](https://www.google.com/search?q=C%2B%2B+undefined+reference+to+template+class+方法)爲stackoverflow解釋的gobs。 – 2013-02-16 19:27:35

回答

11

通常要在頭模板方法,因此在需要時被編譯。如果你真的想隱藏它在實現文件中,你必須明確地實例化Graph.cpp模板像

template class Graph<string>; 

既然你需要做的,對於每一個類型T你打算與Graph<T>使用,點模板類有些失敗,並且最好將所有內容都放到標題中

+0

看來我還不夠聰明:現在我把cpp的定義添加到頭文件中(額外的定義或者把它加上大括號加到函數聲明中)給我一個函數的例子! – leon22 2013-02-16 19:41:32

+1

請參閱我的更新回答 – emesx 2013-02-16 19:50:14

+0

請注意,實際實例化類的實例以使編譯器生成適當的方法是不夠的。您需要使用'模板類ClassName ;'語法來使其正常工作。你不能堅持'ClassName 實例;'並且期望編譯器確定它需要所有的方法(它應該能夠做到的)。當類模板包含在多個cpp文件中時,您可能希望這樣做以停止編譯器一遍又一遍地生成相同的對象。 – Eosis 2017-02-15 13:01:45

6

你需要在頭文件中定義的成員函數,因爲實例化一個模板時,編譯器需要訪問的方法的實現,用實例他們模板參數。

在您的例子:

template <class T> 
class Graph {  
public: 
    void InsertVertex(T val) { 
     Node<T> *temp = new Node<T>(val); 

     if(head == NULL) 
      head = temp; 

     // ... 
    } 

    // ... 

private: 
    Node<T> *head; 
};