0

I am having this issue when compiling C++ in Visual Studio 2022:

Error   LNK2019 unresolved external symbol "public: __cdecl QueueInterface<char>::QueueInterface<char>(int)" (??0?$QueueInterface@D@@QEAA@H@Z) referenced in function "bool __cdecl isPalindrome(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)"...

I have developed in Java for years, but I clearly don't understand the basics of C++ to solve what I assume is a simple issue. I have commented out the code and determined that the way I am constructing this QueueInterface class is not right. I would greatly appreciate any assistance to help me understand what I am missing.

The main() is below:

#include <iostream>
#include <string>

#include "QueueInterface.h"

using namespace std;

int main()
{
    QueueInterface<char> aQueue(25);

}

The header file:

#pragma once

#ifndef QUEUE_INTERFACE_
#define QUEUE_INTERFACE_

using namespace std;

template<class ItemType>
class QueueInterface
{
public:
    /* Not sure why the book left out the constructor. Not sure how this would be possible otherwise */
    QueueInterface(int length);

    /** Sees whether this queue is empty.
     @return  True if the queue is empty, or false if not. */
     bool isEmpty();

    /** Adds a new entry to the back of this queue.
     @post  If the operation was successful, newEntry is at the
        back of the queue.
     @param newEntry  The object to be added as a new entry.
     @return  True if the addition is successful or false if not. */
     bool enqueue(const ItemType& newEntry);

    /** Removes the front of this queue.
     @post  If the operation was successful, the front of the queue
        has been removed.
     @return  True if the removal is successful or false if not. */
     bool dequeue();

    /** Returns the front of this queue.
     @pre  The queue is not empty.
    @post  The front of the queue has been returned, and the
       queue is unchanged.
     @return  The front of the queue. */
     ItemType peekFront() ;

    /** Destroys this queue and frees its memory. */
    virtual ~QueueInterface() { }

private:
    ItemType* queue;
    int size;
    int length;
}; // end QueueInterface
#endif

The implementing file:

#include <iostream>
#include "QueueInterface.h"

using namespace std;

template<class ItemType>
QueueInterface<ItemType>::QueueInterface(int thisLength) : length(thisLength), size(0) {
    queue = new ItemType[length];
}

template<class ItemType>
bool QueueInterface<ItemType>::isEmpty()  {
    return size == 0;
}

template<class ItemType>
bool QueueInterface<ItemType>::enqueue(const ItemType& newEntry) {
    if (size == length - 1) {
        return false;
    }

    queue[size] = newEntry;
    size++;
    return true;
}

template<class ItemType>
bool QueueInterface<ItemType>::dequeue() {
    for (int i = 1; i <= length; i++) {
        if (i == length) {
            queue[i - 1] = NULL;
        }
        else {
            queue[i - 1] = queue[i];
        }
    }

    size--;
    return true;
}

template<class ItemType>
ItemType QueueInterface<ItemType>::peekFront()  {
    return queue[0];
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
WolverinEli
  • 59
  • 1
  • 5
  • The code is mostly fine (and you are instantiating the class in `main()` correctly), however you can't split a templated class into separate `.h` and `.cpp` files in the manner that you are trying. The simplest solution would be to remove `#include "QueueInterface.h"` from `QueueInterface.cpp`, and then add `#include "QueueInterface.cpp"` at the bottom of `QueueInterface.h` (and then, consider renaming `QueueInterface.cpp` to something more like `QueueInterface.ipp` or the like) – Remy Lebeau Feb 22 '23 at 01:43
  • The "implementing class" is not a class. Templates in C++ don't have "implementing classes". – Sam Varshavchik Feb 22 '23 at 01:43
  • @RemyLebeau, thanks for the help! Although, if I remove `#include "QueueInterface.h"` from `QueueInterface.cpp`, then `QueueInterface.cpp` won't build because it doesn't know what any of the methods I am referencing is. I think I'm relating it too closely to java's interface object. – WolverinEli Feb 22 '23 at 01:55
  • I see I can just copy and paste the contents of the methods into the header file, which I guess works. It doesn't seem to create a proper contract, but I don't really care. Thank you everyone for your help! – WolverinEli Feb 22 '23 at 02:02
  • 1
    @WolverinEli "*if I remove `#include "QueueInterface.h"` from `QueueInterface.cpp`, then `QueueInterface.cpp` won't build*" - correct, when it is built as its own translation unit, which you are not supposed to do in this situation (ie, take it out of your build project/makefile, etc), hence the extra `#include` at the bottom of the `.h` file is needed instead. – Remy Lebeau Feb 22 '23 at 02:18
  • 2
    @WolverinEli "*I see I can just copy and paste the contents of the methods into the header file, which I guess works*" - you could do that, or you could just `#include` the file that defines the method bodies, as I suggested. That is as close as you can get to separating declaration from implementation for a template class. Did you read the [duplicate](https://stackoverflow.com/questions/495021/) yet? – Remy Lebeau Feb 22 '23 at 02:22
  • @RemyLebeau Yeah, excluding the file from my project worked in conjunction with your first comment, thanks! – WolverinEli Mar 14 '23 at 01:55

0 Answers0