C++ 通过指针更新派生 class 对象中的变量

C++ Updating a variable in object of derived class via pointer

我正在构建一个链表,其中的节点都链接到 Head。 Head 派生自节点,但 Head 需要指向最后一个节点的指针。请参阅代码顶部的注释。

/*      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) {}
};

如何在添加新节点时更改更改变量 Base::last,例如:

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

我想用虚函数来更新变量,但是根据这个post:Calling virtual functions inside constructors,不行,所以我不想这样做。那么这种链表有没有好的实现方式呢?

谢谢...

class Base : public Node {
    ...
    // Factory method to create child nodes
    Node* getNode(Node* parent) {
        Node* newNode = new Node(parent);
        last = newNode;
        return newNode;
    }
}

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

我添加了一个标志值,这样我们就可以知道我们实际上访问了 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;
}

如果把引用派生class的部分拉出来再内联,这个应该没有问题。但是请注意,在定义派生 class.

之后,我需要定义引用派生 class 的函数

如果您确定最后一个节点将始终是一个 Base 对象,那么使用 static_cast<Base*> 可能还不错。

这个应该更容易理解,仍然使用 static_cast,因为你想通过 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{});
}

反正我不明白基地的必要性class。 您不能简单地在某个地方(例如一个结构)存储两个指针,一个用于列表的头部,一个用于最后一个节点吗?