CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    May 2010
    Posts
    6

    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?

  2. #2
    Join Date
    Nov 2018
    Posts
    122

    Re: LNK2019 linker error when initializing an object

    All your templates need to be in the .h file.

  3. #3
    Join Date
    May 2010
    Posts
    6

    Re: LNK2019 linker error when initializing an object

    Quote Originally Posted by salem_c View Post
    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.

  4. #4
    Join Date
    Nov 2018
    Posts
    122

    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).

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,827

    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)

  6. #6
    Join Date
    May 2010
    Posts
    6

    Re: LNK2019 linker error when initializing an object

    Quote Originally Posted by salem_c View Post
    > 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;
    };

  7. #7
    Join Date
    Nov 2018
    Posts
    122

    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.

    Code:
            qt.addQueue(i);
    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
  •  





Click Here to Expand Forum to Full Width

Featured