Thread: Linker Error (undefined reference)

  1. #1
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034

    Linker Error (undefined reference)

    Ugh, I hate making so many topics lately.. but I've been reading a book and end up having a problem every 50 pages or so.

    I've got two problems, anyone mind helping me with:
    1.) I get an error about some code I got from a C++ programming book:

    c:\programming\projects\game\v0001\bitvector.h(19) : warning C4800: 'unsigned long' : forcing value to bool 'true' or 'false' (performance warning)

    Code:
    class Bitvector
    {
    protected:
      unsigned long int *m_array;
    
    public:
      Bitvector (int);
      ~Bitvector ();
          
      bool operator[] (int p_index)
      {
        int cell = p_index / 32;
        int bit = p_index % 32;
        
        return (m_array[cell] & (1 << bit)) >> bit;
      }
    };
    I think I understand the error, but why must the code in the book that says it compiles in MSVC6 not work, agh.. is the only way to fix it to typecast it (if that works)?


    2.) I've got a problem with my code, which I will naturally blame on templates. MSVC6 errors out:
    Code:
    Main.obj : error LNK2001: unresolved external symbol "public: __thiscall Array<class Monster>::Array<class Monster>(int)" (??0?$Array@VMonster@@@@QAE@H@Z)
    Main.obj : error LNK2001: unresolved external symbol "public: __thiscall Array<class Monster>::~Array<class Monster>(void)" (??1?$Array@VMonster@@@@QAE@XZ)
    Main.obj : error LNK2001: unresolved external symbol "public: int __thiscall Array<class Monster>::Resize(int)" (?Resize@?$Array@VMonster@@@@QAEHH@Z)
    What I find interesting though is it only complains about the constructor, the deconstructor, and the resize method (top three in the .cpp file, which IS in my Project List), when I've used other methods from that class also. This is the part using the methods:

    Code:
    //Main.cpp (Is in the Project List)
    #include "Array.h"
    #include "Monster.h"
    
    Array<Monster> MonsterArray (32);
    int g_monsterCount = 0;
    
    bool AddMonster ()
    {
      if (g_monsterCount == MonsterArray.Size ()) {
        MonsterArray.Resize (MonsterArray.Size () + 32);
      }
    
      MonsterArray[g_monsterCount].SetX(GetRand (0, 640));
      MonsterArray[g_monsterCount].SetY(GetRand (0, 640));
      MonsterArray[g_monsterCount].SetHealth(11 + GetRand (0, 10));
    
      ++g_monsterCount;
    
      return true;
    }
    
    //Array.h
    template< typename Datatype >
    class Array
    {
    private:
      Datatype* m_array;
      int m_size;
    
    public:
      Array (int);
      ~Array ();
    
      Datatype& operator[] (int p_index) {
        if (p_index >= m_size || p_index < 0) {
          std::cout << "Error. The element used in the array does not exist." << std::endl;
    
          return m_array[m_size - 1];
        } else {
          return m_array[p_index];
        }
      }
      
      operator Datatype* () {
        return m_array;
      }
      
      int Resize (int);
      int Remove (int);
      int Insert (Datatype, int);
    
      void Display ();
      int Size()
      {
        return m_size;   
      }
    
      bool ReadFile (const char*);
      bool WriteFile (const char*);
    };
    
    //Array.cpp (Is in the Project List)
    #include "Array.h"
    
    template< typename Datatype >
    Array<Datatype>::Array (int p_sizeInitial)
    {
      m_array = new Datatype[p_sizeInitial];
      m_size = p_sizeInitial;
    }
    
    template< typename Datatype >
    Array<Datatype>::~Array ()
    {
      if (m_array != 0)
        delete[] m_array;
    
      m_array = 0;
    }
    
    template< typename Datatype >
    int Array<Datatype>::Resize (int p_sizeChanged)
    {
     //removed for post
    }
    
    template< typename Datatype >
    int Array<Datatype>::Insert (Datatype p_item, int p_index)
    {
     //removed for post
    }
    
    //Monster.h
    #ifndef MONSTER_H_
    #define MONSTER_H_
    
    class Monster
    {
    private:
      int x;
      int y;
      int m_health;
      int m_count;
    
    public:
      Monster () : x(0), y(0), m_health(0) {}
    
      int RetX ();
      int RetY ();
      
      void SetX (int);
      void SetY (int);
    
      int GetHealth ();
      void SetHealth (int);
    };
    
    #endif //MONSTER_H_
    
    //Monster.cpp (Is in the Project List)
    #include "Monster.h"
    
    int Monster::RetX ()
    {
      return x;
    }
    
    //etc etc etc
    In Dev-Cpp I also get the errors, but it calls it "[Linker error] undefined reference to `Array<Monster>::~Array()'", etc.

    I searched the internet and found solutions: 1) you are declaring the method in the class in .h, but not coding the method in the .cpp not the solution: I have coded it in .cpp, 2) in MSVC6 you can add the .h files under Settings->Link->Object/Library not the solution: didnt seem to work, 3) some MFC library that you need to use, but this isnt using MFC code so that solution didnt effect me.

    Any help REALLY appreciated! thanks in advance,

    EDIT: Array.cpp, and Array.h work stand-alone... so something else must be causing this error. Maybe the fact I am using the Monster class which is inside the Monster.h, as a parameter to the template Array class which is in Array.h, and its just getting confused?
    Last edited by Dae; 07-15-2005 at 03:00 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by Dae
    1.) I get an error about some code I got from a C++ programming book:

    c:\programming\projects\game\v0001\bitvector.h(19) : warning C4800: 'unsigned long' : forcing value to bool 'true' or 'false' (performance warning)

    Code:
    class Bitvector
    {
    protected:
      unsigned long int *m_array;
    
    public:
      Bitvector (int);
      ~Bitvector ();
          
      bool operator[] (int p_index)
      {
        int cell = p_index / 32;
        int bit = p_index % 32;
        
        return (m_array[cell] & (1 << bit)) >> bit;
      }
    };
    I think I understand the error, but why must the code in the book that says it compiles in MSVC6 not work, agh.. is the only way to fix it to typecast it (if that works)?
    It's a warning not an error, your code should compile/link properly... you just need to be aware of the warning and what the message the compiler is telling you means and if it will have any effect (unforeseen) on your program.

    Quote Originally Posted by Dae
    2.) I've got a problem with my code, which I will naturally blame on templates. MSVC6 errors out:
    Remove Array.Cpp from the project and instead copy everything that was in Array.Cpp and put it into Array.H and everything should work. Yes it has to do with templates.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    cut your main file down to just this line.
    Array<Monster> MonsterArray (32);

    Do the errors persist? I bet they do. I told you before what you have to do. You have to put templated code into headers so that the compiler can instantiate it correctly. Whjat you are trying to do is known as the separation model. This only works when a compiler supports export and it is used correctly. The only compiler I know of that supports export is comeau computings one. And to see why export doesn't do what you think read this and this .
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  4. #4
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by hk_mp5kpdw
    It's a warning not an error, your code should compile/link properly... you just need to be aware of the warning and what the message the compiler is telling you means and if it will have any effect (unforeseen) on your program.
    Oh yeah the program wasnt compile/linking properly because of error 2., so its not 1. thats causing that, and being a only a warning.. will still compile. That makes sense, coo thanks.

    But does that code look fine? I mean can you usually eliminate warnings? maybe by type casting? Anyone know a better way to make the 'bool operator[] (int p_index)'?

    Code:
    Remove Array.Cpp from the project and instead copy everything that was in Array.Cpp and put it into Array.H and everything should work. Yes it has to do with templates.
    Alright, well.. this situation being so complex.. thats the only solution? I prefer to have the .cpp, and .h seperate, its just easier to manage for me.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If you like to have the cpp and h files separate, then at the bottom of your h file (before the end of the header guard) add #include "Array.cpp". This will be the equivalent of putting all the code into the .h file, but you can still keep it separate. Then remove the cpp file from the project.

  6. #6
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Stoned_Coder
    cut your main file down to just this line.
    Array<Monster> MonsterArray (32);

    Do the errors persist? I bet they do. I told you before what you have to do. You have to put templated code into headers so that the compiler can instantiate it correctly. Whjat you are trying to do is known as the separation model. This only works when a compiler supports export and it is used correctly. The only compiler I know of that supports export is comeau computings one. And to see why export doesn't do what you think read this and this .
    Wow, thanks, that cleared it up. Nice links.., damn the export feature would have been so nice if it worked the way they wanted it to to start with.

    I guess I can go with the inclusion model for templates.. not a huge deal. Of course too bad about the large compiling time problem..

    Code:
     	If you like to have the cpp and h files separate, then at the bottom of your h file (before the end of the header guard) add #include "Array.cpp". This will be the equivalent of putting all the code into the .h file, but you can still keep it separate. Then remove the cpp file from the project.
    Oh yeah, thats a great idea.. thats perfect for seperating the template, thanks a lot


    Now all I need to know is if that warning MSVC6 is giving me is anything major (is it a portability issue too?), or if theres a better way to impliment that operator so there is nothing to warn about.

    Thanks for the responses guys.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. C OpenGL Compiler Error?
    By Matt3000 in forum C Programming
    Replies: 12
    Last Post: 07-07-2006, 04:42 PM
  4. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM
  5. Problem with OpenGL tutorial
    By 2Biaz in forum Windows Programming
    Replies: 18
    Last Post: 09-16-2004, 11:02 AM