【发布时间】:2011-10-24 11:03:13
【问题描述】:
我有一些关于封装的一般性问题,因为它与可维护性有关。这是我用来帮助构建解析树的示例类。 (为了教育,我避免使用 STL。)
Node 类描述树中的一个节点。管理类ParseTree(未显示)负责以有意义的树状方式构建和维护Node 对象的集合。
// contents of node.h, not including header guard or namespace
class Token;
class Node {
public:
static const Node* FindParent(const Node* p_root, const Node* p_node);
static int Height(const Node* p_root);
static void Print(const Node* p_root);
Node(const Token * p_tok=0) : p_left_(0), p_right_(0), p_tok_(p_tok) {}
~Node() { delete p_left_; delete p_right_; }
const Node* p_left(void) const { return p_left_; }
const Node* p_right(void) const { return p_right_; }
const Token* p_tok(void) const { return p_tok_; }
private:
friend class ParseTree;
Node* p_left_;
Node* p_right_;
Token* p_tok_;
};
以下四个主题与封装有关。
Node类中的静态方法被声明为静态,因为它们可以在不使用任何私有成员的情况下进行表述。我想知道他们是否应该住在Node之外的公共命名空间中,或者可能作为ParseTree中的静态成员。我的决定是否应该由ParseTree负责树的事实主导,并且按照这种逻辑,函数应该存在于ParseTree中?在相关说明中,静态方法位于
Node而不是ParseTree的原因是因为ParseTree被大量成员填满。我读过保持类的小而敏捷对于可维护性更好。我是否应该不遗余力地找到不依赖私有成员访问的方法并将它们从我的类定义中拉出来,并将它们放入与类相同的命名空间中分组的函数中?我还阅读了一些关于避免在私有成员上使用 mutator 的建议,因为它往往会破坏封装,所以我最终只有访问器,并让
ParseTree使用它与Node的友谊来处理任何修改。这真的比拥有变异器并结束与ParseTree的友谊更好吗?如果我添加 mutators,那么Node可以在其他上下文中重用,而无需添加其他友谊。如果我添加修改器并从
Node中删除静态函数,我觉得我可以将数据成员公开并删除所有访问器/修改器/朋友声明。我的印象是,这种方法是不好的形式。如果每个私有成员都有访问器/突变器对,我应该对我的设计持怀疑态度吗?如果我的方法还有什么明显和错误的地方我不想问,我会很高兴听到的。
【问题讨论】:
-
你的论点在兜圈子,当我想到这些问题时,我就会发生这种情况。我不会太担心它,你看起来你知道你在做什么。但是很快 1) 我认为它们不应该在 Node.js 中。 2) 是的,全局函数。 3)我认为重用Node没有什么优势,好像它没有任何价值,让它与ParseTree联系在一起。 4) 不,因为对于像 Node 这样简单的东西来说,所有公开都是可能的。
-
'Mutator',天哪,Setter 和 Getter 有什么问题?
-
过去几年我大部分时间都在做底层工作(IC 设计、hdl、嵌入式 C)。我的一个好朋友在向我描述面向对象设计时总是使用访问器和修改器,所以当我想到与私有成员交互的公共成员函数时,这就是我的想法。
标签: c++ data-structures coding-style encapsulation