-
March 15th, 2024, 11:33 PM
#1
LNK2019 linker error when initializing an object
Hi all,
This is the code that I have. I got this code and I need to work with it:
Code:
#include <iostream>
#include "queueType.h"
int main()
{
queueType<int> qt(100);
for (int i = 0; i < 100; i++)
{
qt.addQueue(i);
}
return 0;
}
Code:
// queueTpe.h:
#pragma once
#include <iostream>
#include "queueADT.h"
template <class Type>
class queueType : public queueADT<Type>
{
public:
//const queueType<Type>& operator=(const queueType<Type>&);
queueType();
queueType(int queueSize = 100);
queueType(const queueType<Type>& otherQueue);
~queueType();
bool isEmptyQueue() const;
bool isFullQueue() const;
void initializeQueue();
Type front() const;
Type back() const;
void addQueue(const Type& queueElement);
void deleteQueue();
void moveNthFront(unsigned int value_iter);
private:
int maxQueueSize;
int count;
int queueFront;
int queueRear;
Type* list;
};
Code:
// queueType.cpp:
#include "queueType.h"
template <class Type>
bool queueType<Type>::isEmptyQueue() const
{
return (count == 0);
}
template <class Type>
bool queueType<Type>::isFullQueue() const
{
return (count == maxQueueSize);
}
template <class Type>
void queueType<Type>::initializeQueue()
{
queueFront = 0;
queueRear = maxQueueSize - 1;
count = 0;
}
template <class Type>
Type queueType<Type>::front() const
{
assert(!isEmptyQueue());
return list[queueFront];
}
template <class Type>
Type queueType<Type>::back() const
{
assert(!isEmptyQueue());
return list[queueRear];
}
template <class Type>
void queueType<Type>::addQueue(const Type& newElement)
{
if (!isFullQueue())
{
queueRear = (queueRear + 1) % maxQueueSize;
count++;
list[queueRear] = newElement;
}
else
{
std::cout << "Cannot add to a full queue." << std::endl;
}
}
template <class Type>
void queueType<Type>::deleteQueue()
{
if (!isEmptyQueue())
{
count--;
queueFront = (queueFront + 1) % maxQueueSize;
}
else
{
std::cout << "Cannot remove from an empty queue" << std::endl;
}
}
template <class Type>
void queueType<Type>::moveNthFront(unsigned int value_iter)
{
if (value_iter < maxQueueSize)
{
Type front_val = list[0];
list[0] = list[value_iter];
list[value_iter] = front_val;
}
else
{
std::cout << " ERROR: The iter value is larger than the maximum queue size." << std::endl;
}
}
template <class Type>
queueType<Type>::queueType()
{
maxQueueSize = 100;
queueFront = 0;
queueRear = maxQueueSize - 1;
count = 0;
list = new Type[maxQueueSize];
}
template <class Type>
queueType<Type>::queueType(int queueSize)
{
if (queueSize <= 0)
{
std::cout << "Size of the array to hold the queue must be positive." << std::endl;
std::cout << "Creating an array of size 100." << std::endl;
maxQueueSize = 100;
}
else
{
maxQueueSize = queueSize;
}
queueFront = 0;
queueRear = maxQueueSize - 1;
count = 0;
list = new Type[maxQueueSize];
}
template <class Type>
queueType<Type>::queueType(const queueType<Type>& otherQueue)
{
queueFront = 0;
queueRear = otherQueue.maxQueueSize - 1;
count = 0;
list = new Type[otherQueue.maxQueueSize];
// copy the actual contents.
for (int i = 0; i < otherQueue.maxQueueSize; i++)
{
list[i] = otherQueue.list[i];
}
}
template <class Type>
queueType<Type>::~queueType()
{
delete[] list;
}
Code:
// queueADT.h:
#pragma once
template <class Type>
class queueADT
{
public:
virtual bool isEmptyQueue() const = 0;
virtual bool isFullQueue() const = 0;
virtual void initializeQueue() = 0;
virtual Type front() const = 0;
virtual Type back() const = 0;
virtual void addQueue(const Type& queueElement) = 0;
virtual void deleteQueue() = 0;
};
When I build it, I get the following errors:
Code:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: __cdecl queueType<int>::queueType<int>(int)" (??0?$queueType@H@@QEAA@H@Z) referenced in function main foo_bar_08 C:\Users\woo\source\repos\foo_bar_08\foo_bar_08.obj 1
Error LNK2019 unresolved external symbol "public: __cdecl queueType<int>::~queueType<int>(void)" (??1?$queueType@H@@QEAA@XZ) referenced in function main foo_bar_08 C:\Users\woo\source\repos\foo_bar_08\foo_bar_08.obj 1
Error LNK2019 unresolved external symbol "public: void __cdecl queueType<int>::addQueue(int const &)" (?addQueue@?$queueType@H@@QEAAXAEBH@Z) referenced in function main foo_bar_08 C:\Users\woo\source\repos\foo_bar_08\foo_bar_08.obj 1
Error LNK1120 3 unresolved externals foo_bar_08 C:\Users\woo\source\repos\foo_bar_08\x64\Debug\foo_bar_08.exe 1
This doesn't make sense. All of the files are located in the same project. What is not being detected by the linker?
-
March 16th, 2024, 01:44 AM
#2
Re: LNK2019 linker error when initializing an object
All your templates need to be in the .h file.
-
March 17th, 2024, 08:25 PM
#3
Re: LNK2019 linker error when initializing an object
 Originally Posted by salem_c
All your templates need to be in the .h file.
But they are... aren't they? What do you mean?
[edit]
Also, why is this issue a problem when linking and not when compiling?
Last edited by s09; March 17th, 2024 at 08:34 PM.
-
March 17th, 2024, 11:56 PM
#4
Re: LNK2019 linker error when initializing an object
> But they are... aren't they?
No, they're all in your queueType.cpp file.
Copy the contents of your queueType.cpp into your queueType.h file.
> Also, why is this issue a problem when linking and not when compiling?
Because the queueType.h file currently contains only enough information that the compiler knows that a method queueType<int>::addQueue(int const &) exists somewhere, but it doesn't have the information to create that function (the actual template).
-
March 18th, 2024, 04:36 AM
#5
Re: LNK2019 linker error when initializing an object
For templates, the definition needs to be in the .h file - not declaration in the .h file with the definition (body) in a .cpp file as you have in post #1
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 18th, 2024, 01:26 PM
#6
Re: LNK2019 linker error when initializing an object
 Originally Posted by salem_c
> But they are... aren't they?
No, they're all in your queueType.cpp file.
Copy the contents of your queueType.cpp into your queueType.h file.
> Also, why is this issue a problem when linking and not when compiling?
Because the queueType.h file currently contains only enough information that the compiler knows that a method queueType<int>::addQueue(int const &) exists somewhere, but it doesn't have the information to create that function (the actual template).
Hi, sorry... I really don't get it. Isn't the purpose of queueType.h to contain the declarations and queueType.cpp to contain the implementation code?
I haven't touched C++ (especially templates) for some time and feel rusty.
If so, then should my queueType.h look like this?
Code:
#pragma once
#include <iostream>
#include "queueADT.h"
template <class Type>
class queueType : public queueADT<Type>
{
public:
const queueType<Type>& operator=(const queueType<Type>&);
template <class Type>
queueType(unsigned int queueSize = 100);
template <class Type>
queueType(const queueType<Type>& otherQueue);
template <class Type>
~queueType();
template <class Type>
bool isEmptyQueue() const;
template <class Type>
bool isFullQueue() const;
template <class Type>
void initializeQueue();
template <class Type>
Type front() const;
template <class Type>
Type back() const;
template <class Type>
void addQueue(const Type& queueElement);
template <class Type>
void deleteQueue();
template <class Type>
void moveNthFront(unsigned int value_iter);
private:
int maxQueueSize;
int count;
int queueFront;
int queueRear;
Type* list;
};
-
March 18th, 2024, 10:32 PM
#7
Re: LNK2019 linker error when initializing an object
> I haven't touched C++ (especially templates) for some time and feel rusty.
And yet you continue to ignore what people are telling you.
Let's make it easy for you.
Go back to your original .h file and add one line to the end of it.
Code:
// queueTpe.h:
#pragma once
#include <iostream>
#include "queueADT.h"
template <class Type>
class queueType : public queueADT<Type>
{
public:
//const queueType<Type>& operator=(const queueType<Type>&);
queueType();
queueType(int queueSize = 100);
queueType(const queueType<Type>& otherQueue);
~queueType();
bool isEmptyQueue() const;
bool isFullQueue() const;
void initializeQueue();
Type front() const;
Type back() const;
void addQueue(const Type& queueElement);
void deleteQueue();
void moveNthFront(unsigned int value_iter);
private:
int maxQueueSize;
int count;
int queueFront;
int queueRear;
Type* list;
};
// Yes, really!
#include "queueType.cpp"
Templates are like the pre-processor on steroids.
When you wrote this in main.cpp, the compiler NEEDS to know about this.
Code:
template <class Type>
void queueType<Type>::addQueue(const Type& newElement)
{
if (!isFullQueue())
{
queueRear = (queueRear + 1) % maxQueueSize;
count++;
list[queueRear] = newElement;
}
else
{
std::cout << "Cannot add to a full queue." << std::endl;
}
}
The compiler then goes off and generates some code for when Type = int
But it can't do that unless it sees the template.
And if it can't do that, then you get your linker error.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|