C++ keep getting error LNK2019: unresolved external symbol

22,760

Solution 1

You need to put all the template implementations that you have in your .cpp file in the header file, or in a file included by the header. And don't try to compile the implementation file. Some systems attempt to compile files with a .cpp suffix. The compiler needs to see the code in order to instantiate templates.

Solution 2

at the bottom of DynIntStack.h, put

#include <DynIntStack.cpp>

what's happening is the compiler doesn't see the template implementation code so cannot emit anything for it.

Share:
22,760
chadpeppers
Author by

chadpeppers

Updated on October 07, 2020

Comments

  • chadpeppers
    chadpeppers over 3 years

    I tried to google this but always come back with different issues. I am getting 3 unresolved externals when I try to compile this program:

    1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall DynIntStack<char>::~DynIntStack<char>(void)" (??1?$DynIntStack@D@@QAE@XZ) referenced in function _main
    1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall DynIntStack<char>::pop(char &)" (?pop@?$DynIntStack@D@@QAEXAAD@Z) referenced in function _main
    1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall DynIntStack<char>::push(char)" (?push@?$DynIntStack@D@@QAEXD@Z) referenced in function _main
    

    DynIntStack.h

    /****************************************************************************
    DynIntStack class.
    
    Chad Peppers
    
    This class creates a object for stacking nodes
    
    In addition, there should be member functions to perform the following 
    operations:
    - Push to the stack
    - Pop to the stack
    - Function to check if empty
    
    ****************************************************************************/
    // Specification file for the DynIntStack class
    #ifndef DYNINTSTACK_H
    #define DYNINTSTACK_H
    
    template <class T>
    class DynIntStack
    {
    private:
       // Structure for stack nodes
       struct StackNode
       {
          T value;        // Value in the node
          StackNode *next;  // Pointer to the next node
       };
    
       StackNode *top;      // Pointer to the stack top
    
    public:
       // Constructor
       DynIntStack()
          {  top = NULL; }
    
       // Destructor
       ~DynIntStack();
    
       // Stack operations
       void push(T);
       void pop(T &);
       bool isEmpty();
    }; 
    #endif
    

    DynIntStack.cpp

    /****************************************************************************
    DynIntStack class.
    
    Chad Peppers
    
    This class creates a object for stacking nodes
    
    In addition, there should be member functions to perform the following 
    operations:
    - Push to the stack
    - Pop to the stack
    - Function to check if empty
    
    ****************************************************************************/
    
    #include <iostream>
    #include "DynIntStack.h"
    using namespace std;
    
    /*************************************************************************
    Basic class constructor.
    
    Input Parameters:  Information to build the  stack
    
    Return Type:  void
    
    *************************************************************************/
    
    template<class T>
    DynIntStack<T>::~DynIntStack()
    {
       StackNode *nodePtr, *nextNode;
    
       // Position nodePtr at the top of the stack.
       nodePtr = top;
    
       // Traverse the list deleting each node.
       while (nodePtr != NULL)
       {
          nextNode = nodePtr->next;
          delete nodePtr;
          nodePtr = nextNode;
       }
    }
    
    /*************************************************************************
    Function to push an item in the stack
    
    Input Parameters:  T
    
    Return Type:  void
    
    *************************************************************************/
    
    template<class T>
    void DynIntStack<T>::push(T num)
    {
       StackNode *newNode; // Pointer to a new node
    
       // Allocate a new node and store num there.
       newNode = new StackNode;
       newNode->value = num;
    
       // If there are no nodes in the list
       // make newNode the first node.
       if (isEmpty())
       {
          top = newNode;
          newNode->next = NULL;
       }
       else  // Otherwise, insert NewNode before top.
       {
          newNode->next = top;
          top = newNode;
       }
    }
    
    /*************************************************************************
    Function to pop an item in the stack
    
    Input Parameters:  T
    
    Return Type:  void
    
    *************************************************************************/
    template<class T>
    void DynIntStack<T>::pop(T &num)
    {
       StackNode *temp; // Temporary pointer
    
       // First make sure the stack isn't empty.
       if (isEmpty())
       {
          cout << "The stack is empty.\n";
       }
       else  // pop value off top of stack
       {
          num = top->value;
          temp = top->next;
          delete top;
          top = temp;
       }
    }
    
    /*************************************************************************
    Basic class deconstructor.
    
    Input Parameters:  None
    
    Return Type:  void
    
    *************************************************************************/
    template<class T>
    bool DynIntStack<T>::isEmpty()
    {
       bool status;
    
       if (!top)
          status = true;
       else
          status = false;
    
       return status;
    }
    

    main.cpp

    #include <iostream>
    #include "DynIntStack.h"
    using namespace std;
    
    int main(){
    
        int value = 0;
        char value2;
        //DynIntStack<int> stack;
        DynIntStack<char> stack1;
    
        cout << "Pushing 1\n";
        stack1.push('T');
        stack1.pop(value2);
        cout << value2;
    
        system("pause");
        return 0;
    }
    
  • EdChum
    EdChum about 12 years
    If I had a pound for everytime I see this question
  • juanchopanza
    juanchopanza about 12 years
    @EdChum or an upvote :-)
  • EdChum
    EdChum about 12 years
    @juanchopanza yep, 'tis me that that upvoted you, it does seem that we get these template linker errors every 2-3 days
  • chadpeppers
    chadpeppers about 12 years
    Very frustrating! That is only on templates?
  • juanchopanza
    juanchopanza about 12 years
    @Chad yes. Think of templates as partial code that needs specific template arguments at compile time in order to be instantiated. The compiler basically makes code out of the template. This has to happen before compilation. I hope that made sense...
  • Karol Borkowski
    Karol Borkowski about 4 years
    Why is this answer voted down since the solution actually works?
  • Oskar Skog
    Oskar Skog about 4 years
    Other answers say the same thing, and 2 years earlier.