结构体需要访问类的私有实例变量

C++ - Struct needs access to private instance variable of class

本文关键字:实例 变量 访问 结构体      更新时间:2023-10-16

我的c++有点生疏,所以我想知道你是否可以帮助我。基本上,我有两个结构体和一个类,结构体需要访问类的私有实例变量。

#ifndef TREE_H
#define TREE_H
#include <iostream>
struct Node {
    ...
    inline void addEdge(Edge* e);
};
inline void Node::addEdge(Edge* e) {
    char ch = inp[e->startIndex];
    edges[ch] = e;
}
struct Edge {
    Node* next = new Node();
    int startIndex = 0;
    friend std::ostream& operator<<(std::ostream& out, Edge e) {
        int index = inp.size() - e.startIndex + endIndex + 1;   // Here the edge needs access to the private members of the Tree class such as string inp, and int endIndex
        // ... do things with index
        return out;
    }
};

class Tree {
public:
    Tree();
    friend std::ostream& operator<<(std::ostream& out, Tree s);
private:
    Node* root = nullptr;
    int endIndex = 0;
    std::string inp;
    void foo();
    std::ostream& printTree(std::ostream& out, Node* curr, std::string append="");
};
#endif // TREE_H

显然上面的代码不起作用。我想把结构体移到类里面。然后是<<Edge的操作符给了我一个"无效使用非静态数据成员'endIndex'"错误。我确信将工作的一个想法是传递一个引用/指针到endIndex作为Edge的成员,当我创建Edge,但我想知道什么可能是一个更好的方法去做这个

我建议使用访问者模式。

这里有一个简短的,不完整的例子,给你一个概念:

class Tree
{
    Node _Node;
    std::list<Node> _Children;
public:
    ... // other stuff, like AddChild(), etc.
    void Traverse(Visitor visitor)
    {
        visitor.HandleNodeData(_Node.Data);
        traverseChildren(visitor);
    }
};

我还会考虑将Tree类实现为模板

对于任何人将来的参考,我现在使用指针解决方案;似乎能完成任务。我对此唯一的疑问是,Tree类中的endIndex是否一定需要在堆栈上(我认为它需要)。有人能解释一下吗?

#ifndef TREE_H
#define TREE_H
#include <iostream>
struct Node {
    ...
    inline void addEdge(Edge* e);
};
inline void Node::addEdge(Edge* e) {
    char ch = inp[e->startIndex];
    edges[ch] = e;
}
struct Edge {
    Edge(int start, int* endIndex) {        
        this->startIndex = start;
        this->endIndex = endIndex;
    }
    Node* next = new Node();
    int startIndex = 0;
    int* endIndex;
    friend std::ostream& operator<<(std::ostream& out, Edge e) {
        std::string value = inp.substr(e.startIndex,  *e.endIndex - e.startIndex + 1);
        out << "(---- " << value << "[" << e.startIndex << ", " << *e.endIndex << "] ---->)";
        return out;
    }
};

class Tree {
public:
    Tree();
    friend std::ostream& operator<<(std::ostream& out, Tree s);
private:
    Node* root = nullptr;
    int* endIndex = new int;   // am i correct in saying this needs to be on the stack? 
    std::string inp;
    void foo();
    std::ostream& printTree(std::ostream& out, Node* curr, std::string append="");
};
#endif // TREE_H