Dual List: Unauthorized External

Possible duplicate:
Why can templates be implemented only in the header file?
What is an undefined link / unresolved external character error and how to fix it?

Again, this is homework, and my instructor gave us a lot of feedback, but I'm still lost for this compilation.

When I put the main function in the implementation file, the program compiles and works fine. However, when I put the main function in main.cpp, the compiler complains:

unresolved external symbol "public: __thiscall doublyLinkedList<int>::doublyLinkedList<int>(void)" ( ??0?$doublyLinkedList@H @@ QAE@XZ ) referenced in function 

Header file

 #ifndef H_doublyLinkedList #define H_doublyLinkedList #include <iostream> #include <cassert> using namespace std; //Definition of the node template <class Type> struct nodeType { Type info; nodeType<Type> *next; nodeType<Type> *back; }; template <class Type> class doublyLinkedList { public: const doublyLinkedList<Type>& operator= (const doublyLinkedList<Type> &); //Overload the assignment operator. void initializeList(); //Function to initialize the list to an empty state. //Postcondition: first = NULL; last = NULL; count = 0; bool isEmptyList() const; //Function to determine whether the list is empty. //Postcondition: Returns true if the list is empty, // otherwise returns false. void destroy(); //Function to delete all the nodes from the list. //Postcondition: first = NULL; last = NULL; count = 0; void print() const; //Function to output the info contained in each node. void reversePrint() const; //Function to output the info contained in each node //in reverse order. int length() const; //Function to return the number of nodes in the list. //Postcondition: The value of count is returned. Type front() const; //Function to return the first element of the list. //Precondition: The list must exist and must not be empty. //Postcondition: If the list is empty, the program // terminates; otherwise, the first // element of the list is returned. Type back() const; //Function to return the last element of the list. //Precondition: The list must exist and must not be empty. //Postcondition: If the list is empty, the program // terminates; otherwise, the last // element of the list is returned. bool search(const Type& searchItem) const; //Function to determine whether searchItem is in the list. //Postcondition: Returns true if searchItem is found in // the list, otherwise returns false. void insert(const Type& insertItem); //Function to insert insertItem in the list. //Precondition: If the list is nonempty, it must be in // order. //Postcondition: insertItem is inserted at the proper place // in the list, first points to the first // node, last points to the last node of the // new list, and count is incremented by 1. void deleteNode(const Type& deleteItem); //Function to delete deleteItem from the list. //Postcondition: If found, the node containing deleteItem // is deleted from the list; first points // to the first node of the new list, last // points to the last node of the new list, // and count is decremented by 1; otherwise, // an appropriate message is printed. doublyLinkedList(); //default constructor //Initializes the list to an empty state. //Postcondition: first = NULL; last = NULL; count = 0; doublyLinkedList(const doublyLinkedList<Type>& otherList); //copy constructor ~doublyLinkedList(); //destructor //Postcondition: The list object is destroyed. public: int count; nodeType<Type> *first; //pointer to the first node nodeType<Type> *last; //pointer to the last node public: void copyList(const doublyLinkedList<Type>& otherList); //Function to make a copy of otherList. //Postcondition: A copy of otherList is created and // assigned to this list. }; #endif 

Implementation File:

 #include <iostream> #include <cassert> #include "doublyLinkedList.h" using namespace std; template <class Type> doublyLinkedList<Type>::doublyLinkedList() { first= NULL; last = NULL; count = 0; } template <class Type> bool doublyLinkedList<Type>::isEmptyList() const { return (first == NULL); } template <class Type> void doublyLinkedList<Type>::destroy() { nodeType<Type> *temp; //pointer to delete the node while (first != NULL) { temp = first; first = first->next; delete temp; } last = NULL; count = 0; } template <class Type> void doublyLinkedList<Type>::initializeList() { destroy(); } template <class Type> int doublyLinkedList<Type>::length() const { return count; } template <class Type> void doublyLinkedList<Type>::print() const { nodeType<Type> *current; //pointer to traverse the list current = first; //set current to point to the first node while (current != NULL) { cout << current->info << " "; //output info current = current->next; }//end while }//end print template <class Type> void doublyLinkedList<Type>::reversePrint() const { nodeType<Type> *current; //pointer to traverse //the list current = last; //set current to point to the //last node while (current != NULL) { cout << current->info << " "; current = current->back; }//end while }//end reversePrint template <class Type> bool doublyLinkedList<Type>:: search(const Type& searchItem) const { bool found = false; nodeType<Type> *current; //pointer to traverse the list current = first; while (current != NULL && !found) if (current->info >= searchItem) found = true; else current = current->next; if (found) found = (current->info == searchItem); //test for //equality return found; }//end search template <class Type> Type doublyLinkedList<Type>::front() const { assert(first != NULL); return first->info; } template <class Type> Type doublyLinkedList<Type>::back() const { assert(last != NULL); return last->info; } template <class Type> void doublyLinkedList<Type>::insert(const Type& insertItem) { nodeType<Type> *current; //pointer to traverse the list nodeType<Type> *trailCurrent; //pointer just before current nodeType<Type> *newNode; //pointer to create a node bool found; newNode = new nodeType<Type>; //create the node newNode->info = insertItem; //store the new item in the node newNode->next = NULL; newNode->back = NULL; if(first == NULL) //if the list is empty, newNode is //the only node { first = newNode; last = newNode; count++; } else { found = false; current = first; while (current != NULL && !found) //search the list if (current->info >= insertItem) found = true; else { trailCurrent = current; current = current->next; } if (current == first) //insert newNode before first { first->back = newNode; newNode->next = first; first = newNode; count++; } else { //insert newNode between trailCurrent and current if (current != NULL) { trailCurrent->next = newNode; newNode->back = trailCurrent; newNode->next = current; current->back = newNode; } else { trailCurrent->next = newNode; newNode->back = trailCurrent; last = newNode; } count++; }//end else }//end else }//end insert template <class Type> void doublyLinkedList<Type>::deleteNode(const Type& deleteItem) { nodeType<Type> *current; //pointer to traverse the list nodeType<Type> *trailCurrent; //pointer just before current bool found; if (first == NULL) cout << "Cannot delete from an empty list." << endl; else if (first->info == deleteItem) //node to be deleted is //the first node { current = first; first = first->next; if (first != NULL) first->back = NULL; else last = NULL; count--; delete current; } else { found = false; current = first; while (current != NULL && !found) //search the list if (current->info >= deleteItem) found = true; else current = current->next; if (current == NULL) cout << "The item to be deleted is not in " << "the list." << endl; else if (current->info == deleteItem) //check for //equality { trailCurrent = current->back; trailCurrent->next = current->next; if (current->next != NULL) current->next->back = trailCurrent; if (current == last) last = trailCurrent; count--; delete current; } else cout << "The item to be deleted is not in list." << endl; }//end else }//end deleteNode template <class Type> void doublyLinkedList<Type>::copyList(const doublyLinkedList<Type>& otherList) { //cout << "The definition of this function is left as an exercise." << endl; //cout << "See Programming Execrise 9." << endl; template <class Type> doublyLinkedList<Type>::doublyLinkedList(const doublyLinkedList<Type>& otherList) { // cout << "The definition of the copy constructor is left as an exercise." << endl; // cout << "See Programming Execrise 9." << endl; } template <class Type> const doublyLinkedList<Type>& doublyLinkedList<Type>::operator= (const doublyLinkedList<Type> &) // cout << "Overloading the assignment operator is left as an exercise." << endl; // cout << "See Programming Execrise 9." << endl; } template <class Type> doublyLinkedList<Type>::~doublyLinkedList() { //cout << "Definition of the destructor is left as an exercise." << endl; //cout << "See Programming Execrise 9." << endl; } 

The main function:

 //Program to test various operations on a doubly linked list #include <iostream> #include "doublyLinkedList.h" using namespace std; int main() { char choice; int n = 0; doublyLinkedList<int> myList; cout<<"this is a test"<<endl; do { cout<<"Main Menu:"<<endl; cout<<"Choice of operations to perform on Dobule Linked List"<<endl; cout<<"Create list values : C"<<endl; cout<<"Initialize List: Z"<<endl; cout<<"Check List Empty: M"<<endl; cout<<"Destroy List: E "<<endl; cout<<"Print List : P"<<endl; cout<<"Reverse printed list: R"<<endl; cout<<"Length of List: L"<<endl; cout <<"Front of List: F"<<endl; cout<<"Back of List: B"<<endl; cout<<"Search list: S"<<endl; cout<<"Insert List: I"<<endl; cout<<"delete list: D"<<endl; cout<<"use copy constructor : U" <<endl; cout <<"quit: Q"<<endl; cin >> choice; if ((choice == 'I' )|| (choice =='D')|| (choice == 'S')) { cout<<"Enter value to manipulate: "<<endl; cin >> n; } switch ( choice) { case 'C': cout<<"Please enter a list"<<endl; while(n!= -999){ myList.insert(n); cin>>n;} break; case 'S': if (myList.search(n)) cout<< " List contains: "<<n<<endl; else cout<<"List does not contain "<<n<<endl; break; case 'I': myList.insert(n); cout<<"element was inserted"<<endl; break; case 'D': myList.deleteNode(n); cout<<"node was deleted"<<endl; break; case 'L': cout<<"Length is \n"<<endl; myList.length(); break; case 'B': cout<<"back element is : "<< myList.back(); break; case 'F' : cout<<"front element is "<<myList.front(); break; case 'Z' : myList.initializeList(); cout<<"list initialized"<<endl; case 'M': if (myList.isEmptyList()) cout<<"is empty"<< endl; else cout<<"is not empty"<<endl; break; case 'E': myList.destroy(); cout<<"list destroyed"<<endl; break; case 'P': myList.print(); break; case'R': cout<<"reversed"<<endl; myList.reversePrint(); break; } }while(choice!= 'Q'); return 0; } 

I am looking for guidance. I know that the answer is really simple, and I just don't see it. I was thinking about using the extern keyword, but I'm not sure how to use it. As I said in the tags, this is homework, so I'm not looking for a quick solution that I want to extract from my mistakes. I really appreciate this site and all the participants.

All the code that I posted here was available for free to the publisher of the book, I did not use my original code, except for main.cpp

+6
source share
2 answers

You need to move your implementation to the header file. Unlike ordinary functions, the compiler should be able to see all the template code in the place of use.

See the answers in this question for more information:

Why can templates be implemented only in the header file?

+5
source

The problem is that you do not have the template definitions available in your main compilation module (where they are used).

This means that you need to have explicit instances for the types with which it is used.

  • Add

     template class doublyLinkedList<int>; 

    to the end doublelyLinkedList.cpp to explicitly create an instance.

  • Or include cpp in the header,

  • or directly in main.cpp

+3
source

Source: https://habr.com/ru/post/927051/


All Articles