Reputation: 3224
My C++ is a bit rusty so I was wondering if you could help me out. Basically, I have two structs and a class and the structs need access to the private instance variables of the class.
#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
So obviously the above code doesn't work. I was thinking I would move the structs inside the class. But then the << operator for Edge gives me an "invalid use of non-static data member 'endIndex'" error. One idea I'm sure will work is to pass a reference/pointer to endIndex as a member of Edge when I create the Edge but I was wondering what might be a better way to go about this.
Upvotes: 1
Views: 802
Reputation: 3224
For anyone's future reference, I went with the pointer solution for now; seems to get the job done. My only doubt about this is whether endIndex in the Tree class needs to necessarily be on the stack (I think it does). Can anyone clarify?
#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
Upvotes: 0
Reputation: 650
I would propose to use the visitor pattern.
Here's a brief, incomplete example, to give you the idea:
class Tree
{
Node _Node;
std::list<Node> _Children;
public:
... // other stuff, like AddChild(), etc.
void Traverse(Visitor visitor)
{
visitor.HandleNodeData(_Node.Data);
traverseChildren(visitor);
}
};
I would also consider to implement the Tree class as a template.
Upvotes: 1