Safe/Correct 指针的使用

Safe/Correct use of pointers

我知道您不应该 return 指向成员数据的指针或引用,因为它会破坏封装。但我不确定在这种情况下是否发生了这种情况,我可以使用一些说明...

树头-

#include "TreeNode.h"
class Tree
{
public:
    explicit Tree(Tree* treeToCopy);
    explicit Tree(TreeNode*);
    TreeNode& getRootNode() const;
private:
    TreeNode* rootNodeOfExpressionTree;
};

Tree.cpp-

#include "Tree.h"


Tree::Tree(Tree* treeToCopy)
{
    rootNodeOfExpressionTree = &treeToCopy->getRootNode();
}
Tree::Tree(TreeNode* rootNodeOfExpressionTree)
    :rootNodeOfExpressionTree(rootNodeOfExpressionTree)
{
}//empty constructor body

TreeNode& Tree::getRootNode() const
{
    return *rootNodeOfExpressionTree;
}

我的问题是关于 getRootNode() 方法的。由于 rootNodeOfExpressionTree 是一个指针,我正在取消引用它并 returning 引用它指向的任何内容,那么我没有破坏封装正确吗?

我认为你正在破坏封装,因为如果某些代码调用 getRootNode(),它可以更改数据 rootNodeOfExpressionTree 指向而无需通过 class(甚至 rootNodeOfExpressionTree),这会破坏封装。

你并没有破坏封装,就像用户可以自己做一样 TreeNode *my_node = new TreeNode; 用户只能调用 TreeNode 的 public 方法,因为你返回一个 const参考,他甚至不能调用会改变事物的方法。

所以我认为这不是问题。相比之下,this 是可能有问题的代码:

class ServoController {
    void setPosition( int x ) { /* do some stuff to move servo, then */ current_position = x; }
    int &getPosition( void ) { return current_position; } // <--- don't do this!
// ...
    int current_position;
} ;

通过返回对成员变量 current_position 的引用,您允许用户在不实际移动舵机的情况下扰乱您的状态。这可能会使程序不同步并引起麻烦。

我不认为这与指针有任何关系。我会说你正在破坏封装,因为 TreeNode 对象应该是一个实现细节,而 public 接口理想情况下应该只处理 TreeNode 对象用于存储的内容。

我假设你的 Tree 被用来存储一些非结构数据?

然后 encapsulation 理想情况下应该隐藏 public API 中不是元素的所有内容,或者是 [=23 的元素的迭代器=]非结构性 数据。想想 STL 个容器。您不需要查看 std::list 使用的 链表 根指针 ,因为它隐藏了实现细节。但是您确实看到非结构数据的第一个元素 std::list::front()

打破封装没有问题。 None 随便。问题在于打破 不变性 。封装是一个神话。不变量是真实存在的。

此处 getRootNode 的调用者可以访问 Tree 成员指向的数据。这意味着调用者无法更改指针本身,但可以更改指针指向的数据。我意识到这可能令人困惑,所以这里有一个简单的例子:

struct A {
    A() : member(new int(42)) {}
    int& get() const { return *member; }

    private:
    int* member;
};

....
A a; // *a.member is 42
int& x = a.get();
x = 56; // *a.member is 56!

问题是,此数据是否不变量值得保护?我不知道,只有你知道。