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

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

本文关键字:对象 变量 派生 指针 更新 C++      更新时间:2023-10-16

我正在构建一个链表,其中节点都链接到 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?

我正在考虑使用虚函数来更新变量,但根据这篇文章:在构造函数中调用虚拟函数,这是一个不行的,所以我不想这样做。 那么有没有实现这种类型的链表的好方法呢?

谢谢。。。

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

我添加了一个标志值,以便我们可以判断我们实际上访问了Base类:

#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;
}

如果拉出引用派生类的部分,然后将其内联,则应该没有问题。但请注意,在定义派生类之后,我需要定义引用派生类的函数。

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

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

这个应该更容易理解并且仍然使用static_cast,因为您想通过基类进行追加。

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

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