v0rtex
v0rtex

Reputation: 59

Modifying private pointer of object within same type (but different object) public method

I've been attempting to create a node class which mimics a node on a graph. Currently, storage of the predecessor and successor nodes are stored via a node pointer vector: std::vector<Node*> previous. The vectors for the predecessor/successor nodes are private variables and are accessible via setters/getters.

Currently, I am dealing with updating the pointer values when adding a new node. My current method to update the predecessor/successor nodes is through this method (the method is the same for successor/previous nodes, just name changes):

void set_next(std::vector<Node*> new_next) {
    this->next.clear();

    for (Node* node : new_next) {
        this->next.push_back(node);
    }
}

This works for the current node but I was wondering the best way to update the new_next nodes that are passed in, especially the most 'C++'-esque way to accomplish this. I have previously written a method which adds individual nodes to the successor/predecessor vector:

void add_next(Node* new_node, bool one_way = false) {
    this->next.pushback(new_node);
    if (!one_way) {
        new_node->add_prev(this, one_way = true);
    }
}

The one_way variable was used to determine the depth(?) of the add_next() call. If it is true, it will add to the successor set and then add to the predecessor set of new_node. Since the boolean value is set to false when the new_node->add_next() method call occurs, it will only add to the predecessor set and not attempt to call add_next()/add_prev() again. This solution does work, but I'd rather not have the one_way variable and would prefer that the method would be private.

Here is the structure of the class currently:

class Node {
private:
    std::vector<Node*> previous;
    std::vector<Node*> next;
    boost::any data;
public:
    std::vector<Node*> get_previous()
    void set_previous(std::vector<Node*> new_previous)
    
    std::vector<Node*> get_next()
    void set_next(std::vector<Node*> new_next)

    void add_prev(Node* new_node, bool one_way = false)
    void add_next(Node* new_node, bool one_way = false)
}

Avoiding the one_way parameter, it seems my best solution would be to just create an add_next/add_prev method that only updates the current node, not the passed node, unlike the solution above. With this solution, when adding new nodes, I could call the inverse of the add_next/add_prev on the new node. However, I have an inkling there may be a better solution for this.

Thank you!

Upvotes: 0

Views: 71

Answers (1)

mnhaouas
mnhaouas

Reputation: 101

I think this should get you going (edge-cases left to you to figure out, if any):

template<typename T>
class Node {
// Everything made public for debugging purposes, change this to fit your needs
public:
    std::vector<Node<T>*> previous;
    std::vector<Node<T>*> next;
    T data;

    Node(T val) {
        data = val;
    }
    void set_next(std::vector<Node<T>*>& new_next);
};

template<typename T>
void Node<T>::set_next(std::vector<Node<T>*>& new_next) {
    next = new_next;

    for (Node<T>* node : new_next)
        node->previous.push_back(this);
}


int main() {
    // Little proof of concept where 0 is parent to 1, 2, 3
    Node<int> one = 1;
    Node<int> two = 2;
    Node<int> three = 3;

    Node<int> zero = 0;

    std::vector<Node<int>*> new_next = { &one , &two, &three };

    zero.set_next(new_next);

    return 0;
}

To sum up the differences:

  • Use templates, boost::any is non standard and is all around terrible for this task.
  • Leverage operators (= makes a copy of std::vectors).
  • Leverage reference types (this way you can modify the argument passed to your function).

Upvotes: 1

Related Questions