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.
Author by
chadpeppers
Updated on October 07, 2020Comments
-
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 about 12 yearsIf I had a pound for everytime I see this question
-
juanchopanza about 12 years@EdChum or an upvote :-)
-
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 about 12 yearsVery frustrating! That is only on templates?
-
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 about 4 yearsWhy is this answer voted down since the solution actually works?
-
Oskar Skog about 4 yearsOther answers say the same thing, and 2 years earlier.