2009-11-22 76 views
1

問題修復。非常感謝!C++中的鏈接錯誤

我在代碼以下錯誤如下所示具有:

錯誤如下:

$克++ main.cpp中Neighbor.cpp Graph.cpp
/TMP/ccclDcUN的.o:在功能main':
main.cpp:(.text+0xc1): undefined reference to
格拉夫::添加(INT,鄰居&) '
main.cpp中:(文本+ 0xd3):未定義參考`格拉夫::添加(INT,鄰居&)'
collect2:ld返回1退出狀態

會發生什麼問題?

// FILENAME: Graph.cpp 
#include "Neighbor.h" 
#include "Graph.h" 

template <typename NS> 
void Graph<NS>::add(int id,NS& n){ 
    if(id>=adj_list.size()) 
     while(adj_list.size()<id+1) 
      adj_list.push_back(list<NS>()); 
    adj_list[id].push_back(n); 
} 


template <typename NS> 
void Graph<NS>::remove(int id,NS& n){ 
    if(id<adj_list.size()){ 
     adj_list[id].remove(n); 
    } 
} 


// FILENAME: Graph.h 
#ifndef GRAPH_H 
#define GRAPH_H 

#include "utils.h" 
#include <vector> 
#include <list> 

class Neighbor; 

template <typename NS> 
class Graph { 
    private: 
     std::vector<std::list<NS> > adj_list; 
    public: 
     void add(int,NS&); 
     void remove(int,NS&); 
     inline typename std::vector<std::list<NS> >::iterator begin() { return adj_list.begin(); } 
     inline typename std::vector<std::list<NS> >::iterator end() { return adj_list.end(); } 
}; 

#endif 


// FILENAME: Neighbor.cpp 
#include "Neighbor.h" 
#include <iostream> 

Neighbor::Neighbor(int id,float e,float p):id(id),edge_cost(e),price(p){} 

bool operator==(const Neighbor& n1,const Neighbor& n2) { 
    if(&n1==&n2) return true; 
    return false; 
} 

ostream& operator<<(ostream& ostr,const Neighbor& n1) { 
    ostr<<"["<<n1.id<<","<<n1.price<<","<<n1.edge_cost<<"]"; 
    return ostr; 
} 


// FILENAME: Neighbor.h 
#ifndef NEIGHBOR_H 
#define NEIGHBOR_H 

#include <iosfwd> 


class Neighbor { 
    private: 
     int id; 
     float edge_cost; 
     float price; 
    public: 
     Neighbor(int,float,float p=0.0); 
     friend bool operator==(const Neighbor&,const Neighbor&); 
     friend std::ostream& operator<<(std::ostream&,const Neighbor&); 
}; 

#endif 


// FILENAME: utils.h 
#ifndef UTILS_H 
#define UTILS_H 

#include <iostream> 
#include <fstream> 
#include <stack> 
#include <queue> 
#include <vector> 
#include <list> 
#include <string> 
#include <algorithm> 

namespace utility { 

typedef std::pair<int,int> ii; 
typedef std::vector<int> vi; 
typedef std::vector<ii> vii; 
typedef std::vector<vii> vvii; 
typedef std::stack<int> si; 
typedef std::queue<int> qi; 

} 

#define UTILITY_TR(c,i) for(typeof((c).begin()) i = (c).begin() ; i!=(c).end() ; ++i) 
#define UTILITY_ALL(c) (c).begin(),(c).end() 
#define UTILITY_CPRESENT(c,x) (find(all(c),x) != (c).end()) 

#endif 

// FILENAME: main.cpp 
#include "utils.h" 
#include "Neighbor.h" 
#include "Graph.h" 

using namespace std; 

int main() { 
    Graph<Neighbor> graph; 
    Neighbor n1(1,10); 
    Neighbor n2(0,10); 
    graph.add(0,n1); 
    graph.add(1,n2); 

    cout<<"Printing graph"<<endl; 
    cout<<"--------------"<<endl; 

    UTILITY_TR(graph,it) { 
     UTILITY_TR(*it,n) { 
      cout<<*n<<endl; 
     } 
    } 
}; 
+2

當我們在之前建議您不要在頭文件中使用'namespace std'並且爲類型使用有意義的名稱時,我們是認真的。 –

+0

該死!我怎麼錯過那一行!抱歉! – user855

+0

而且,這是重複的;看到這個問題:http://stackoverflow.com/questions/1639797/template-issue-causes-linker-error-c(特別是GMan的美味解釋)。 –

回答

1

您需要在.h文件中定義Graph函數(添加和刪除),以便鏈接器c找到它。

我試着想像信封這樣的模板。在您輸入字母(定義類型)之前發送它(編譯)是無意義的。看作是cpp文件是編譯的,它是有道理的,不應該有模板類型的cpp文件。

HTH!

3

我最常做的是手動驗證符號存在於庫:

objdump --syms foo.o 

這將輸出包含在.o文件將符號列表...(因爲它是一個鏈接錯誤,你應該有.o文件...(確保你傳遞-c到g ++讓它在編譯後停止))...然後你可以直觀地驗證對象是否有你認爲它的符號...