簡體   English   中英

朋友類需要包含或轉發聲明 C++?

[英]Friend classes need to include or forward declare c++?

在嘗試使用隊列構建二叉樹時,我一直在與錯誤作斗爭。 問題是哪些類應該包含哪些文件以及如何從其他類中引用對象? 我將我的文件放入 IDE,試圖找出問題所在,結果如下。 目前我的問題是在 Queue.h 文件中,treePtr“沒有命名類型”。 你可以在這里看到這個問題的演變這個問題與其他帖子不同,因為這兩個類是友元類。 這就帶來了循環依賴的問題。 我嘗試了包含文件和前向聲明的各種組合,但一種組合會導致一種類型的問題,另一種會產生不同的錯誤。

這是主類:

#include <cstdlib>
#include "Tree.cpp"

using namespace std;

int main() {

    Tree tree;
    tree.addTreeNode(5);

return 0;

}

這是 Queue.h:

#ifndef QUEUE_H_
#define QUEUE_H_

class Tree;  //Was instructed to put this here

class Queue {

    friend class Tree;

    private:
        typedef struct node {
            Tree::treePtr treeNode; //Here is the problem
            node* next;
        }* nodePtr;

        nodePtr head;
        nodePtr current;

public:
    Queue();
    virtual ~Queue();
    void push(Tree::treePtr t);  //Here is the problem
    int pop();
    void print();

};

#endif /* QUEUE_H_ */

這是 Tree.h:

#ifndef TREE_H_
#define TREE_H_

#include "Queue.h"  //Was instructed to put this here

class Tree {
    friend class Queue;

    private:

        Queue q;  //Edit: Most likely problem since Queue and Tree are friends

        typedef struct tree {
            int data;
            tree* left;
            tree* right;
        }* treePtr;

        treePtr root;
        int numNodes;

public:
    Tree();
    virtual ~Tree();
    void addTreeNode(int integer);
};

#endif /* TREE_H_ */

這是 tree.cpp

#include <cstdlib>
#include <iostream>

#include "Tree.h"

using namespace std;

Tree::Tree() {
    root = NULL;
    numNodes = 0;
}

void Tree::addTreeNode(int integer) {
    numNodes++;
    treePtr t = new tree;
    t->left = NULL;
    t->right = NULL;
    t->data = integer;

    cout << "add root\n";
    root = t;
    q.push(t);  //This is a problem
    q.print();

}

Tree::~Tree() {
    // TODO Auto-generated destructor stub
}

您必須分別編譯Tree.cpp和(我想您有一個) Queue.cpp ,而不是在main.cpp中包含Tree.cpp

前向聲明適用於友元類,即使您這樣做也是循環的。

#include "Tree.h"放在Queue.cpp文件中,讓編譯器看到完整的聲明。

main.cpp只需放入#include " Tree.h"

為了獲得最終的可執行鏈接,所有生成的目標文件main.o(bj)Tree.o(bj)Queue.o(bj)

另請參閱[為什么我不應該包含 cpp 文件而是使用標題?]請。


正如我現在注意到的,您的實際問題是,您無法從前向聲明的類/結構訪問嵌套類/結構,因為您需要從Queue訪問treePtrtreePtr應該更好地命名為TreeNode或類似的 BTW)。

在這種情況下,您不能將treePtr私有嵌套類型,它必須是公開可見的。

一種可行的方法是將treePtr放在namespace internal_ ,這表明它不打算在 API 之外使用。


另一種可行的方法是使Queue成為一個模板類,它接受任何類型的tree或其他類型的節點。 既然看不到任何用例,為什么Queue需要了解tree的內部規范(除了像復制 aso 之類的瑣碎事情之外),實際上沒有必要將Queue設為friend類。

我最好的猜測是,問題在於,由於類 Queue 和 Tree 是朋友,並且 Tree 有一個 Queue 的實例作為數據成員,因此在嘗試包含文件和轉發聲明時會出現一些沖突。 通過與 Queue 共享數據成員,Tree 類與 Queue 類共享了一個 Queue 對象的實例化,因此有一些不明顯的初始共享正在進行。 @πάντα ῥεῖ 建議將 Queue 設為模板類,以便它可以接受任何類型的對象,而不必與 Tree 耦合(這樣做是為了讓 Queue 類知道如何處理 treePtr 對象)。 使 Queue 成為模板類解決​​了這個問題,因為現在 Tree 類可以有一個 Queue 的實例,而且我可以將 treePtr 類型的對象傳遞給 Queue,而 Queue 事先不知道關於 Tree 類的任何信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM