1

I am building a linked list, where nodes are all linked to Head. The Head is derived from node, but the Head requires a pointer to last node. See the comment at the top of code.

/*      Base <= node <= node <= node
 *       |                       ^
 *       |    ptr to last node   |
 *       -------------------------
 */

class Node {
 private:
    Node* prev;

 public:
    explicit Node(Node* parent) : prev(parent) {

        Node* foo_ptr = this;

        while (foo_ptr->prev != 0) {
            foo_ptr = foo_ptr->prev;
        }

        // foo_ptr points to Base, how can I now change Base::last?
    }
};

class Base : public Node {
 private:
    Node* last;
 public:
    Base() : Node(0), last(this) {}
};

How can I change change variable Base::last when adding new node, for example:

Node* n = new Base;
new Node(n);            // can Node constructor update n->last?

I was thinking to use virtual function to update the variable, but according to this post: Calling virtual functions inside constructors, its a no no so I do not want to do it. So is there a good way of achieving this type of linked list?

Thanks...

Community
  • 1
  • 1
user1135541
  • 1,781
  • 3
  • 19
  • 41

3 Answers3

1

http://coliru.stacked-crooked.com/a/213596aa1ffe7602

I added a flag value so we can tell that we actually accessed the Base class:

#include <iostream>

class Node {
 private:
    Node* prev;

 public:
    inline void changeBaseLast(Node* base);

    explicit Node(Node* parent) : prev(parent) {

        Node* foo_ptr = this;

        while (foo_ptr->prev != 0) {
            foo_ptr = foo_ptr->prev;
        }

        // foo_ptr points to Base
        // now change Base::last 

        changeBaseLast(foo_ptr);
    }

    int data;
};

class Base : public Node {
 private:
    Node* last;

 public:
    int flag;
    Base() : Node(0), last(this), flag(0) {}

};

//Here, we can see that we change the base_ptr to 1.
void Node::changeBaseLast(Node* base) {
    Base* base_ptr = static_cast<Base*>(base);
    base_ptr->flag=1;
}

int main() {
    Node* n = new Base;
    new Node(n);
    std::cout << static_cast<Base*>(n)->flag << std::endl;
}

If you pull out the part that refers to the derived class and then inline it, there should be no problems with this. Notice, though, that I need to define the functions that refer to the derived class after I define the derived class.

If you're sure that the last node will always be a Base object, then using static_cast<Base*> may not be that bad.

V15I0N
  • 396
  • 4
  • 17
CinchBlue
  • 6,046
  • 1
  • 27
  • 58
  • OK, so this works in the application code, I have been programming for a long time, but never used this method before. Its almost like a callback function, thank you... – user1135541 Jun 18 '15 at 22:28
0
class Base : public Node {
    ...
    // Factory method to create child nodes
    Node* getNode(Node* parent) {
        Node* newNode = new Node(parent);
        last = newNode;
        return newNode;
    }
}
V15I0N
  • 396
  • 4
  • 17
  • You can simplify this, as `parent == last` – wimh Jun 18 '15 at 21:12
  • OK, so, for adding the node this would work, now deleting node becomes an issue, if you delete the last node, the base node needs updating. – user1135541 Jun 18 '15 at 21:22
  • Again, add the method to class Base: `Base::recycle(Node** toDelete) { if (*toDelete == NULL) return; if(last == toDelete) {last = toDelete->prev;} else { ... } delete *toDelete; *toDelete =NULL;}` – V15I0N Jun 18 '15 at 22:04
0

This one should be even easier to understand and still uses static_cast, for you want to append by means of the Base class.

class Node {
    private:
        Node* prev;

    public:
        explicit Node() : prev{nullptr} { }

        void setParent(Node *parent) {
            prev = parent;
        }
};

class Base : public Node {
    private:
        Node* last;

    public:
        Base() : Node{}, last{this} { }

        void append(Node *node) {
            node->setParent(last);
            last = node;
        }
};

int main() {
    Node* n = new Base;
    static_cast<Base*>(n)->append(new Node{});
}

Anyway, I don't understand the need of the Base class. Can't you simply store somewhere (as an example a struct) two pointers, one for the head of the list and one for the last node?

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • The linked list Base has additional information that is needed, so in the actual application code there are many more methods and variables in Base class. Thanks... – user1135541 Jun 18 '15 at 22:27