Linker errors

This is a discussion on Linker errors within the C++ Programming forums, part of the General Programming Boards category; I have a header file which contains the class with only function declarations. I then define the function in a ...

  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
    21,461
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    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,046
    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, 01:03 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21