代码之家  ›  专栏  ›  技术社区  ›  LBaelish

安全/正确使用指针[关闭]

  •  0
  • LBaelish  · 技术社区  · 8 年前

    我理解您不应该返回指向成员数据的指针或引用,因为它破坏了封装。但我不确定这是不是发生在这个案件中的事情,我需要一些澄清。。。

    树标题-

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

    树.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是一个指针,我正在取消对它的引用并返回它所指向的任何对象的引用,那么我没有破坏封装,对吗?

    4 回复  |  直到 8 年前
        1
  •  2
  •   SergeyA    8 年前

    打破没有问题 封装 一点也没有。问题是断裂 不变的 封装是一个神话。不变量是真实的。

    打电话给 getRootNode 获取数据的访问权限 Tree member指向。这意味着调用方不能改变指针本身,但它可以改变指针指向的数据。我意识到这可能会让人困惑,所以这里有一个简单的例子:

    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!
    

    问题是,这些数据是 不变的 值得保护吗?我不知道,只有你知道。

        2
  •  1
  •   Dave M.    8 年前

    您不会破坏封装,正如用户只需做 TreeNode *my_node = new TreeNode; 用户只能调用TreeNode的公共方法,因为您返回了 const 引用,他甚至不能调用会改变事情的方法。

    所以我不认为这是一个问题。通过比较, 是潜在的问题代码:

    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 ,您允许用户在不实际移动伺服的情况下扰乱您的状态。这可能会使程序失去同步,并引起悲伤。

        3
  •  1
  •   Galik    8 年前

    我认为这与指针无关。我会说你正在破坏封装,因为 TreeNode 对象应该是一个实现细节,公共接口最好只处理 树节点 对象用于存储。

    我想你的 Tree 是否用于存储一些非结构化数据?

    然后 封装 最好是对公众隐瞒一切 API 它不是元素,也不是元素的迭代器 非结构性的 数据想想 STL 容器。你不需要看到 根指针 链接列表 那个 std::list 因为它是一个隐藏的实现细节。但是你 第一次看到 要素 属于 非结构性的 数据与 std::list::front() .

        4
  •  0
  •   Rakete1111    8 年前

    我认为您正在破坏封装,因为如果某些代码调用 getRootNode() ,它可以更改数据 rootNodeOfExpressionTree 在没有经过课堂的情况下指向 表达式树的根节点 ),这破坏了封装。