2013-02-16 64 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; 
};