簡體   English   中英

C ++如何通過自制的侵入式列表避免使用朋友模板函數

[英]C++ How to avoid friend template functions with home-made intrusive lists

我需要一個侵入式,已排序的雙向鏈接列表。 我不想使用boost :: intrusive,所以我自己做這個,遇到了問題

對於雙鏈表,有幾個操作,這里只是其中之一,將有助於說明我的觀點:

template<typename LIST, typename NODE>
void insertAfter(LIST *list, NODE *node, NODE *newNode)
{
    newNode->prev_ = node;
    newNode->next_ = node->next_;
    if(nullptr == node->next_)
        list->last_ = newNode;
    else
        node->next_->prev_ = newNode;
    node->next_ = newNode;
}

現在假設我有一組對象在一個這樣的列表中,但我希望其膽量是私有的:

struct Object
{
private:
    Object *prev_, *next_;
};

現在,我創建我的列表(請忽略以下事實:當列表為空時,將出現nullptr異常...)。

struct List
{
    Object *first_, *last_;

    void addObject(Object *o)
    {
        insertAfter(this, last_, o);  // not correct when list empty
    }
};

因為prev_和next_是私有的,並且insertAfter沒有訪問權限,所以不會編譯。 這可以很容易地解決:

// Fwd decl
struct List;

struct Object
{
    friend void insertAfter<List, Object>(List *, Object *, Object *);
private:
    Object *prev_, *next_;
};

struct List
{
    Object *first_, *last_;

    void addObject(Object *o)
    {
        insertAfter(this, last_, o);
    }
};

但這打開了一個訪問漏洞,任何人都可以使用insertAfter影響Object的私有成員。 我真正想要的是List成為Object的朋友。 我可以通過不在鏈接列表操作中使用模板來解決此問題(改為使用普通宏),但這顯然有其缺點。 去這里的正確方法是什么?

沿着這些思路怎么樣?

template<class ObjectType>
class List
{
    ObjectType *first_, *last_;

public:
    void addObject(ObjectType *o)
    {
        insertAfter(this, last_, o);
    }

    void insertAfter(ObjectType *node, ObjectType *newNode)
    {
        newNode->prev_ = node;
        newNode->next_ = node->next_;
        if(nullptr == node->next_)
            this->last_ = newNode;
        else
            node->next_->prev_ = newNode;
        node->next_ = newNode;
    }
};

class Object
{
private:
    Object *prev_, *next_;

    friend class List<Object>;
};

int main() {}

不過,我看不出它的冒犯程度實際上不如您以前做的那么好:模板代碼仍然是內聯的,因此您不能阻止人們按照自己的喜好重寫類。 放松一下,對客戶保持合理的信任度:)

您可以封裝侵入性數據,例如:

template <typename Object>
class List
{
public:
    class PrivateData
    {
        friend class List;
    public: // minimal stuff which should be public go here
        PrivateData() : prev_(nullptr), next_(nullptr) {}
    private:
        // other stuff
        Object *prev_, *next_;
    };

    // Other stuff

};

然后在您的對象中:

class Object
{
public:
    List<Object>::privateData listData_;
private:
    // internal data.
};

由於ListData中的所有內容都是私有的,因此用戶無法對listData_進行任何操作,但可以由作為好友的List訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM