空对象模式、递归类和前向声明
我有兴趣执行如下操作,以遵守 Null 对象设计模式并避免大量 NULL 测试:
class Node;
Node* NullNode;
class Node {
public:
Node(Node *l=NullNode, Node *r=NullNode) : left(l), right(r) {};
private:
Node *left, *right;
};
NullNode = new Node();
当然,正如所写,NullNode 在 Node 类声明之前和之后具有不同的内存位置。如果您不想使用默认参数(即删除 Node *r=NullNode),则可以在没有前向声明的情况下执行此操作。
另一种选择是使用一些继承:创建一个具有两个子类(NullNode 和 FullNode)的父类(Node)。那么上面的节点示例将是 FullNode 的代码,上面代码中的 NullNode 将是继承自 Node 的 NullNode 类型。我讨厌通过诉诸继承来解决简单的问题。
所以,问题是:如何在 C++ 中将空对象模式应用于具有默认参数(它们是同一类的实例!)的递归数据结构(类)?
I'm interested in doing something like the following to adhere to a Null Object design pattern and to avoid prolific NULL tests:
class Node;
Node* NullNode;
class Node {
public:
Node(Node *l=NullNode, Node *r=NullNode) : left(l), right(r) {};
private:
Node *left, *right;
};
NullNode = new Node();
Of course, as written, NullNode has different memory locations before and after the Node class declaration. You could do this without the forward declaration, if you didn't want to have default arguments (i.e., remove Node *r=NullNode).
Another option would use some inheritence: make a parent class (Node) with two children (NullNode and FullNode). Then the node example above would be the code for FullNode and the NullNode in the code above would be of type NullNode inheriting from Node. I hate solving simple problems by appeals to inheritence.
So, the question is: how do you apply Null Object patterns to recursive data structures (classes) with default arguments (which are instances of that same class!) in C++?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用
extern
:更好的是,使其成为静态成员:
也就是说,在现有代码和上面的修改中,您泄漏了
Node
的实例。您可以使用auto_ptr
,但这会很危险,因为全局变量和静态变量的销毁顺序不确定(某些全局变量的析构函数可能需要Node::Null
,并且它可能或者到那时可能还没有消失)。Use
extern
:Better yet, make it a static member:
That said, in both existing code, and amendments above, you leak an instance of
Node
. You could useauto_ptr
, but that would be dangerous because of uncertain order of destruction of globals and statics (a destructor of some global may needNode::Null
, and it may or may not be already gone by then).我实际上已经实现了一个递归树(用于 JSON 等),执行类似的操作。基本上,您的基类成为“NULL”实现,其接口是派生类的所有接口的并集。然后,您可以拥有实现各个部分的派生类 - “DataNode”实现数据获取器和设置器等。
这样,您可以对基类接口进行编程,并为自己省去很多麻烦。您设置基本实现来为您执行所有样板逻辑,例如
这样我就不必测试任何内容 - 我只是盲目地调用“
OutputAsINI()
”。整个界面的类似逻辑将使大多数空测试消失。I've actually implemented a recursive tree (for JSON, etc.) doing something like this. Basically, your base class becomes the "NULL" implementation, and its interface is the union of all interfaces for the derived. You then have derived classes that implement the pieces- "DataNode" implements data getters and setters, etc.
That way, you can program to the base class interface and save yourself A LOT of pain. You set up the base implementation to do all the boilerplate logic for you, e.g.
This way I don't have to test anything- I just blindly call "
OutputAsINI()
". Similar logic for your whole interface will make most of the null tests go away.颠倒层次结构。将空节点放在底部:
然后根据需要进行专门化:
示例用法:
输出:
Invert the hierarchy. Put the null node at the base:
Then specialize as needed:
Sample usage:
Output: