2017-04-18 150 views
0

我正在寫一個簡單的Queue類(用於練習)。這個項目由Queue Class使用的一個簡單的整數節點類和它自己的Queue類組成。visual studio鏈接器錯誤

在生成過程中我得到我的C++項目,3個不同的鏈接錯誤列舉如下:

  1. 錯誤LNK2005 「市民:__thiscall節點::節點(INT)」(?? 0Node @@ QAE @ H + Z) 在fmQueue.obj隊列已經定義

  2. 錯誤LNK2005 「公共:__thiscall節點::節點(無效)」(?? 0Node @@ @ QAE XZ) 已經在fmQueue.obj隊列

    定義
  3. 錯誤LNK1169 one or更多重定義符號找到隊列

我沒有看我在哪裏我的介紹課,但我不明白的地方這isuue的來源。

我的代碼:

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; 
} 

回答

1

這是一個常見的問題,是由頭文件中的實現引起的。
會發生什麼是您的fmQueue.cpp編譯單元編譯並定義構造函數。 之後,main.cp編譯並定義相同的函數(因爲它們在包含的頭文件中是可見的)。
所以,當鏈接器試圖將2個編譯單元鏈接在一起時,它會檢測到雙重定義。

所以,這就是爲什麼你應該在.cpp文件中實現函數的原因。
另一個解決方案是解耦頭依賴。您可以在隊列頭中轉發聲明Node類,並且只在隊列的cpp文件中包含該頭。

+0

完美的解釋,將Node類的實現移到一個cpp文件解決了問題。謝謝 – BlooB

0

代替將#include「node.h」放入其他頭文件中,將其放入.cpp文件中。

然後你必須在fmQueue.h中聲明類型。

// fmQueue.h 

class Node; 

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

..... 

// fmQueue.cpp 


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

編譯器只需要知道,會有一種「類節點」在這個時候,它並不需要知道任何節點的成員或方法。