Thread: Linker errors

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    65

    Linker errors

    I have a header file which contains the class with only function declarations. I then define the function in a separate cpp file. However, I get linker errors when I do this. If I define the function in the header file (but outside the class) I don't get linker errors. Why would it matter whether the function was defined inside the header or cpp file?

    The function insertVertex is giving me problems.

    GraphEdgeList.h
    Code:
    #ifndef GRAPHEDGELIST_H
    #define GRAPHEDGELIST_H
    
    #include <vector>
    #include <list>
    
    template <typename Object>
    class Vertex {
    private:
        template <typename> friend class GraphEdgeList;
        Object o;
        int undirectedDegree;
        int inDegree;
        int outDegree;
    public:
        Vertex(const Object& oo = Object()) : o(oo), undirectedDegree(0),
            inDegree(0), outDegree(0)
        {
        }
        const Object& element() const {
            return o;
        }
        void element(const Object& oo) {
            o = oo;
        }
    };
    
    template <typename Object>
    class Edge {
    private:
        template <typename> friend class GraphEdgeList;
        typedef Vertex<Object> Vertex;
        Object o;
        Vertex* origin;
        Vertex* destination;
        bool isDirected;
    public:
        Edge(const Object& oo = Object(), Vertex* org = NULL, Vertex* dst = NULL,
            bool directed = false)
            : o(oo), origin(org), destination(dst), isDirected(directed)
        {
        }
        const Object& element() const {
            return o;
        }
        void element(const Object& oo) {
            o = oo;
        }
    };
    
    /*
     * A graph represented by an edge list
     */
    template <typename Object>
    class GraphEdgeList {
        typedef Vertex<Object> Vertex;
        typedef Edge<Object> Edge;
        std::list<Vertex> V;
        std::list<Edge> E;
    public:
        Vertex& insertVertex(const Object& o);
    };
    
    #ifdef DEFINEINHEADER
    
    template <class Object>
    typename GraphEdgeList<Object>::Vertex&
    GraphEdgeList<Object>::insertVertex(const Object& o) {
        typedef typename GraphEdgeList<Object>::Vertex Vertex;
        V.push_back(Vertex(o));
        return V.back();
    }
    
    #endif
    
    #endif
    GraphEdgeList.cpp
    Code:
    #include "GraphEdgeList.h"
    
    #ifdef DEFINEINCPP
    
    template <class Object>
    typename GraphEdgeList<Object>::Vertex&
    GraphEdgeList<Object>::insertVertex(const Object& o) {
        typedef typename GraphEdgeList<Object>::Vertex Vertex;
        V.push_back(Vertex(o));
        return V.back();
    }
    
    #endif
    main.cpp
    Code:
    #define DEFINEINCPP // this gives linker errors
    //#define DEFINEINHEADER // this works
    #include "GraphEdgeList.h"
    #include <iostream>
    #include <utility>
    #include <string>
    
    int main() {
        GraphEdgeList<std::string> g;
        g.insertVertex("SFO");
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    65
    From what I read, I just have to add another line to the cpp file. However, I'm still getting linker errors. What am I doing wrong?

    Code:
    #include "GraphEdgeList.h"
    
    #ifdef DEFINEINCPP
    
    template <class Object>
    typename GraphEdgeList<Object>::Vertex&
    GraphEdgeList<Object>::insertVertex(const Object& o) {
        typedef typename GraphEdgeList<Object>::Vertex Vertex;
        V.push_back(Vertex(o));
        return V.back();
    }
    
    template class GraphEdgeList<std::string>; // added this line
    
    #endif

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You have to add
    Code:
    #define DEFINEINCPP
    into GraphEdgeList.cpp as well, otherwise it won't be defined. Of course, this is duplication of code, so I'd suggest adding the DEFINEIN* to another .h file which you then include in GraphEdgeList.h. That should solve the problem.

    Also, by the way, I had compiler errors when compiling your code with g++ 4.3 and g++ 4.4. It doesn't like you doing things like this:
    Code:
    typedef Vertex<Object> Vertex;
    Erros:
    Code:
    GraphEdgeList.h:56: error: declaration of ‘typedef class Vertex<Object> GraphEdgeList<Object>::Vertex’
    GraphEdgeList.h:8: error: changes meaning of ‘Vertex’ from ‘class Vertex<Object>’
    If I were you I'd pick a different name.

    [edit] In case you're interested, here's the code I got to compile with g++ 4.3.
    Code:
    $ for file in *.cpp *.h; do echo === $file; cat $file; done
    === GraphEdgeList.cpp
    #define DEFINEINCPP // this gives linker errors
    #include "GraphEdgeList.h"
    
    #ifdef DEFINEINCPP
    
    template <class Object>
    typename GraphEdgeList<Object>::Vertex_&
    GraphEdgeList<Object>::insertVertex(const Object& o) {
        //typedef typename GraphEdgeList<Object>::Vertex Vertex;
        V.push_back(Vertex_(o));
        return V.back();
    }
    
    #include <string>
    
    template class GraphEdgeList<std::string>; // added this line
    
    #endif
    === main.cpp
    #define DEFINEINCPP // this gives linker errors
    //#define DEFINEINHEADER // this works
    #include "GraphEdgeList.h"
    #include <iostream>
    #include <utility>
    #include <string>
    
    int main() {
        GraphEdgeList<std::string> g;
        g.insertVertex("SFO");
    }
    === GraphEdgeList.h
    #ifndef GRAPHEDGELIST_H
    #define GRAPHEDGELIST_H
    
    #include <vector>
    #include <list>
    
    template <typename Object>
    class Vertex {
    private:
        template <typename> friend class GraphEdgeList;
        Object o;
        int undirectedDegree;
        int inDegree;
        int outDegree;
    public:
        Vertex(const Object& oo = Object()) : o(oo), undirectedDegree(0),
            inDegree(0), outDegree(0)
        {
        }
        const Object& element() const {
            return o;
        }
        void element(const Object& oo) {
            o = oo;
        }
    };
    
    template <typename Object>
    class Edge {
    private:
        template <typename> friend class GraphEdgeList;
        typedef Vertex<Object> Vertex_;
        Object o;
        Vertex_* origin;
        Vertex_* destination;
        bool isDirected;
    public:
        Edge(const Object& oo = Object(), Vertex_* org = NULL, Vertex_* dst = NULL,
            bool directed = false)
            : o(oo), origin(org), destination(dst), isDirected(directed)
        {
        }
        const Object& element() const {
            return o;
        }
        void element(const Object& oo) {
            o = oo;
        }
    };
    
    /*
     * A graph represented by an edge list
     */
    template <typename Object>
    class GraphEdgeList {
        typedef Vertex<Object> Vertex_;
        typedef Edge<Object> Edge_;
        std::list<Vertex_> V;
        std::list<Edge_> E;
    public:
        Vertex_& insertVertex(const Object& o);
    };
    
    #ifdef DEFINEINHEADER
    
    template <class Object>
    typename GraphEdgeList<Object>::Vertex&
    GraphEdgeList<Object>::insertVertex(const Object& o) {
        //typedef typename GraphEdgeList<Object>::Vertex Vertex_;
        V.push_back(Vertex(o));
        return V.back();
    }
    
    #endif
    
    #endif
    $
    Notice the #include <string> and the typedefs changed to Vertex_ etc. [/edit]
    Last edited by dwks; 06-12-2009 at 01:01 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linker errors in VC++ 2005
    By C+/- in forum C++ Programming
    Replies: 0
    Last Post: 05-18-2007, 07:42 AM
  2. Sneaky little linker errors...
    By Tozar in forum C++ Programming
    Replies: 8
    Last Post: 10-25-2006, 05:40 AM
  3. Linker errors when compiling
    By The Wazaa in forum C++ Programming
    Replies: 4
    Last Post: 10-07-2006, 12:55 PM
  4. Linker errors with Visual C++
    By codegirl in forum C++ Programming
    Replies: 4
    Last Post: 09-11-2003, 09:20 AM
  5. MSVis-Studio C++ libraries and linker errors
    By kellydj in forum Windows Programming
    Replies: 10
    Last Post: 03-12-2002, 02:03 PM