【问题标题】:Linking error in C++C++中的链接错误
【发布时间】:2009-11-22 23:02:57
【问题描述】:

问题已解决。非常感谢!

我在下面显示的代码中遇到以下错误:

错误如下:

$ g++ main.cpp Neighbor.cpp Graph.cpp
/tmp/ccclDcUN.o: 在函数main':
main.cpp:(.text+0xc1): undefined reference to
Graph::add(int, Neighbor&)' main.cpp:(.text+0xd3): 未定义引用 `Graph::add(int, Neighbor&)'
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;
        }
    }
};

【问题讨论】:

  • 当我们之前建议您不要在头文件中使用using namespace std 并为类型使用有意义的名称时,我们是认真的。
  • 该死!我怎么错过了那一行!对不起!
  • 而且,这是重复的;看到这个问题:stackoverflow.com/questions/1639797/…(特别是 GMan 的美味解释)。
  • 非常感谢!这确实是一件微妙的事情。我必须承认,我才刚刚开始使用模板。因此所有这些麻烦。谈到将函数模板的定义移到 .h 文件中,我看到了一些源代码,其中开发人员将所有代码放在 .h 文件中。而且只有一个.cpp 文件.. main.cpp。这是一种好的代码组织方法吗?
  • 他们所有的代码?肯定不好。唯一常见的是将类模板和函数模板的定义放到header中。

标签: c++ linker-errors


【解决方案1】:

我通常做的是手动验证符号是否存在于库中:

objdump --syms foo.o

这将输出 .o 文件中包含的符号列表...(因为这是链接错误,您应该有 .o 文件...(确保将 -c 传递给 g++ 以使其在编译))...然后您可以直观地验证该对象是否具有您认为的符号...

【讨论】:

    【解决方案2】:

    您需要在.h文件中定义Graph的函数(添加和删除),以便链接器可以找到它。

    我试着把模板想象成信封。在输入字母(定义类型)之前发送它(编译)是荒谬的。由于 cpp 文件是被编译的,所以不应该有模板类型的 cpp 文件是有道理的。

    HTH!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-09
      • 1970-01-01
      相关资源
      最近更新 更多