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。
您不能简单地在某个地方(例如一个结构)存储两个指针,一个用于列表的头部,一个用于最后一个节点吗?
我正在构建一个链表,其中的节点都链接到 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。 您不能简单地在某个地方(例如一个结构)存储两个指针,一个用于列表的头部,一个用于最后一个节点吗?