C++11 用C++实现层次结构中的朋友方法

C++11 用C++实现层次结构中的朋友方法,c++11,friend,C++11,Friend,我目前正在实现某种层次结构,如果子实体附加到父实体,我需要将父实体指定给子实体。我的问题是,我是否可以在父类中使用friend方法解决这个问题,这是否是一种好的编码风格。下面是一个简短的例子来解释我的意思: class Node { Node* parent; Node() : parent(nullptr) { } friend void attachChild(const Node& child) const; friend void detachChil

我目前正在实现某种层次结构,如果子实体附加到父实体,我需要将父实体指定给子实体。我的问题是,我是否可以在父类中使用friend方法解决这个问题,这是否是一种好的编码风格。下面是一个简短的例子来解释我的意思:

class Node {
   Node* parent;

   Node() : parent(nullptr) { }

   friend void attachChild(const Node& child) const;
   friend void detachChild(unsigned long idx) const;
};

class ListNode : public Node {
   std::vector<Node*> childs;

   ListNode() : Node() { this->childs = {}; }

   void attachChild(Node* child) const {
      child->parent = this;
      childs.push_back(child);
   }

   void detachChild(unsigned long idx) const {
      child->parent = nullptr;
      child.erase(child.begin() + idx)
   }
};

class NodeOne : public Node {};
class NodeTwo : public Node {};
class NodeThree : public Node {};
最后一点简短的评论:一个子实体可能只有一个父实体,而在我的场景中,子实体和父实体可能是同一类型。

是的,在这种情况下,这是一种糟糕的编码风格。通常对于这样的继承结构,有关父/子关系的信息保存在节点本身中

ListNode类是冗余的,它的功能实际上属于节点本身,这就是为什么您发现自己需要与该类交朋友

通过简单地向node类添加setParent方法,可以避免使用friend函数。如果要确保只有节点可以处理父/子关系,请将其设置为私有/受保护

class Node {

public:

    Node() : parent(nullptr) { };

    int addChild(Node* child)
    {
        child->setParent(this);
        this->children.push_back(child);

        int idx = this->children.size() - 1;
        return idx;
    };
    void removeChild(unsigned long idx)
    {
        Node* child = children.at(idx);
        child->setParent(nullptr);
        this->children.erase(children.begin() + idx);
    }

private:

    void setParent(Node* node)
    {
        parent = node;
    }

private:

    Node* parent;
    std::vector<Node*> children;
};

使用朋友很少是一个好的选择,这往往是一个坏的设计的迹象。虽然有些情况下很难不使用它,但在您的情况下,最好使用setter/getter函数。除非Node类可以是父类内部的私有内部类,否则使用friend可能是一个不错的解决方案。Node和Parent始终依赖于相同的基类,并且都可以在示例中更新父类。那会有帮助吗?
int main(int argc, char* argv[])
{
    Node parent;
    Node child;
    parent.addChild(&child);
}