0
votes

I am writing a simple Queue class (for exercise). This Project consists of a simple integer Node Class, which Queue Class utilizes, and the Queue class it self.

During build I am getting 3 different linker errors in my c++ project, listed below:

  1. Error LNK2005 "public: __thiscall Node::Node(int)" (??0Node@@QAE@H@Z) already defined in fmQueue.obj Queue

  2. Error LNK2005 "public: __thiscall Node::Node(void)" (??0Node@@QAE@XZ) already defined in fmQueue.obj Queue

  3. Error LNK1169 one or more multiply defined symbols found Queue

I did look at where i am introducing my classes, however i dont understand where this isuue is coming from.

My code:

Node.h:

// Node.h
// 1-way linked node for use in simple integer Queue

#ifndef NODE_H
#define NODE_H

class Node
{
public:
    Node();
    Node(int);

    int data;
    Node *next;
};

Node::Node()
{
    data = -1;
    next = nullptr;
}

Node::Node(int x)
{
    data = x;
    next = nullptr;
}

#endif

fmQueue.h:

#ifndef _FMQUEUE_H
#define _FMQUEUE_H


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

namespace fm
{
    class fmQueue
    {
        Node *_head, *_tail;
        void clearbuf();


    public:

        fmQueue();

        ~fmQueue();

        void deQueue(); // uses front to access data, or remove data
        void enQueue(int); // uses back to sort data, or add data
        void dumQueue();

        //int peek(); // get a copy of the front data without removing it

        bool isEmpty();

    };

}

#endif /* _FMQUEUE_H */

fmQueue.cpp:

#include "fmQueue.h"

using namespace fm;

//---------Private Methods--------
void fmQueue::clearbuf()
{
    _head = _tail = nullptr;
}

//--------Public Methods----------

fmQueue::fmQueue()
{
    clearbuf();
}

fmQueue::~fmQueue()
{
    clearbuf();
}

bool fmQueue::isEmpty()
{
    if (_head == _tail && _head == nullptr)
        return false;
    else
        return true;
}


void fmQueue::enQueue(int data1)
{
    Node *tempNode = new Node;

    tempNode->next = nullptr;
    tempNode->data = data1;

    if (_head == nullptr)
    {
        _head = tempNode;
        _tail = tempNode;
    }


    else
    {
        _tail->next = tempNode;
    }

    _tail = tempNode;
}

void fmQueue::deQueue()
{
    Node *tempNode = new Node;

    if (_head == nullptr)
        std::printf("NOOOOP, THE QUEUE IS EMPTY");

    else
    {
        tempNode = _head;

        _head = _head->next;
        std::cout << "the data dequeued is: " << tempNode->data; //add a print statment to see which node was deleted

        delete tempNode;


    }

}

void fmQueue::dumQueue()
{
    Node *tempNode = new Node;

    if (tempNode)
        while (tempNode->next != nullptr)
        {
            std::cout << "Queue :" << tempNode->data;

            tempNode = tempNode->next;
        }
    else
        std::cout << "Nothing to show";

}

main.cpp:

#include"fmQueue.h"

int main()
{
    fm::fmQueue my_queue;
    my_queue.enQueue(2);
    std::cout << "fiirst done" << std::endl;
    my_queue.enQueue(4);
    std::cout << "second done" <<std::endl;
    my_queue.dumQueue();
    std::cout << "show done" << std::endl;
    my_queue.deQueue();
    std::cout << "delete done" << std::endl;
    my_queue.dumQueue();
    std::cout << "show done" << std::endl;
    my_queue.deQueue();
    std::cout << "delete done" << std::endl;

    return 0;
}
2

2 Answers

1
votes

It's a common problem that's caused by having an implementation in a header file.
What happens is that your fmQueue.cpp compilation unit compiles, and defines the constructor functions. After that, the main.cp compiles and defines the same functions (because they are visible in the included header file).
So when the linker tries to link the 2 compilation units together it detects the double definition.

So, that's why you should implement functions in the .cpp file.
Another solution would be to decouple the header dependency. You can forward declare the Node class in the queue's header, and only actually include the header in the queue's cpp file.

0
votes

Instead of putting #include "node.h" inside the other headers, put it inside the .cpp.

Then you must forward declare the type in fmQueue.h.

// fmQueue.h

class Node;

namespace fm
{
class fmQueue
{
    Node *_head, *_tail;
    void clearbuf();

 .....

// fmQueue.cpp


 #include "fmQueue.h"
 #include "Node.h"
 ....

The compiler just needs to know that there will be a type 'class Node' at this time, it doesn't need to know any of the members or methods of Node.