2017-01-08 73 views
2

我正在C++中實現後綴特里結構,其中我使用三個類Trie,NodeEdge。由於我使用的是類,所以我已經將我的函數/變量聲明分離爲各自的.cpp文件中的頭文件(.hpp)文件及其實現。現在我不習慣這樣做(我通常用於將所有內容寫入一個.cpp文件),但我認爲這對於可讀性和結構都是有利的。C++中的循環指針

所以,我有以下文件:

  • Launcher.cpp,包含main()函數。
  • Trie.hpp,包含函數和變量的聲明。
  • Trie.cpp,包含在Trie.hpp中聲明的函數的實現。
  • Node.hpp,包含函數和變量的聲明。
  • Node.cpp,包含在Node.hpp中聲明的函數的實現。
  • Edge.hpp,包含函數和變量的聲明。
  • Edge.cpp,包含在Edge.hpp中聲明爲 的函數的實現。

現在我已經實現了trie的方式是每個Node都有一個向量類型Edge。另外,我希望Edge有一個指針Node*,以便它指向另一個節點(這是邊緣所做的)。現在雖然這看起來像是一個循環定義,但我記得它可以實現(至少,我曾經能夠在我的程序全部在一個.cpp文件中時做到這一點)。

但由於我們現在有很多的#include s的頂部所有這些單獨的文件,我不得不#include 'Node.hpp'Edge.hpp,並在Node.hpp#include 'Edge.hpp'。如果我不這樣做,我會遇到諸如「邊界未在此範圍內定義」等錯誤。但是,如果我做所有的包括,我得到一個無限循環式的錯誤信息:

enter image description here

我跑的命令是

g++ -std=c++11 -Wall -o program Edge.cpp Node.cpp Trie.cpp Launcher.cpp 

我希望這就是我應該正在運行。有沒有什麼辦法可以在沒有這些錯誤的情況下實現我想要的?如果我將所有內容都放入一個文件,我相信這一點很有用。


編輯:我已經做了在Edge.hpp下,一切似乎是工作的罰款!

#ifndef EDGE_HPP 
#define EDGE_HPP 

#include <string> 

class Node;   //Forward definition 

using namespace std; 

class Edge{ 

    private: 
     string label; 
     Node* pointsTo; 

    public: 
     Edge(); 
     Edge(string, Node*); 
     string getLabel(); 
     Node* getPointsTo(); 

}; 

#endif 
+0

這可能很容易解決。但是你需要顯示你的代碼。 – selbie

+0

在'Edge.hpp'中,前向聲明應該足夠了;如'class Node;'你不需要'#include'Node.hpp「' –

+0

@IgorTandetnik雖然這被認爲是很好的做法嗎?這似乎是作弊。 –

回答

2

這是前向聲明的一個簡單例子。

現在我已經實現了trie的方式是每個節點都有一個類型爲Edge的向量 。

這將被轉換爲這樣的事情,在節點的頭文件:

class Edge; 

class Node { 

public: 
    std::vector<Edge> edges; 

    Node(); 
    ~Node(); 
}; 

這將足以宣佈在其頭文件中的節點。不需要包含Edge的頭文件。現在

,該.cpp文件,定義節點的構造函數和析構函數,必須包含頭文件,使這兩個類是完全聲明。

此外,我希望Edge有一個指針Node *,以便它指向另一個節點(這是邊緣所做的) 。

這只是轉化爲,在邊緣的頭文件:

class Node; 

class Edge { 

public: 
    Node *from_node; 
    Node *to_node; 

    // ... 
}; 

再次,不需要包括Node的頭文件。

Node的頭文件包括Edge「,而不是向前聲明S類的頭文件,可能會被罰款過,只有Edge的頭文件需要以前瞻聲明Node類。

您需要牢記的唯一事情是,任何需要使用Edge類和使用其Node的代碼都需要包含兩個頭文件。僅僅包括Edge將是不夠的,因爲該代碼將不會得到每個Node的聲明,邊緣指向,除非Node的頭文件也包含在內。

此外,有時前向聲明可能會導致無法聲明內聯類方法,而這些方法需要使用前向聲明的類。周圍也有各種各樣的方法。