我有一些关于封装的一般性问题,因为它与可维护性有关。这是我用来帮助构建解析树的示例类。 (出于教育原因,我避免使用 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
类中的静态方法被声明为静态的,因为它们可以在不使用任何私有(private)成员的情况下使用短语。我想知道它们是否应该位于Node
之外的公共(public)命名空间中,或者作为ParseTree
中的静态成员。我的决定是否应该由ParseTree
负责树这一事实决定,并且根据该逻辑函数应该位于ParseTree
中?在相关说明中,静态方法在
Node
而不是ParseTree
中的原因是因为ParseTree
被填满了很多成员。我读过保持类小和敏捷更利于可维护性。我是否应该特意寻找不依赖私有(private)成员访问的方法,并将它们从我的类定义中提取出来,并将它们放入与该类相同的命名空间内的函数中?我还阅读了一些关于避免对私有(private)成员使用修改器的建议,因为它往往会破坏封装,所以我最终只有访问器,并让
ParseTree
使用它与节点
。这真的比拥有突变器和结束与ParseTree
的友元更好吗?如果我添加修改器,则Node
可以在其他上下文中重用,而无需添加另一个友元。如果我从
Node
添加修改器并删除静态函数,我觉得我可以只公开数据成员并删除所有访问器/修改器/友元声明。我的印象是这种方法是不好的形式。如果每个私有(private)成员都有访问器/修改器对,我是否应该怀疑我的设计?如果我的方法还有其他明显错误但我没想过要问,我很乐意听到。
最佳答案
问问自己,什么是节点?显然,它可能有 parent 、左 child 和右 child 。它还包含指向某些数据的指针。节点有高度吗?这取决于上下文,您的节点是否有可能在某个时候成为循环的一部分? ParseTree 有高度的概念,节点似乎没有。
老实说,我建议你先把你的程序逻辑弄好,然后你就可以担心面向对象的花里胡哨了。 随着您的继续,您提出的问题可能会自动得到解答。
关于c++ - 为可维护性和封装性构建 C++ 类层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7017605/