1. 程式人生 > >C++ 用模板實現List的Node基類

C++ 用模板實現List的Node基類

    看了C++的單例模式後,啟發很大,剛好要寫一個List,就在想能不能用模板來實現List的Node節點。

    在這裡直接上重點,完成後的程式碼:

#ifndef DONZ_TEMPLATE_NODE_H
#define DONZ_TEMPLATE_NODE_H


template<typename SubNode>
class Node
{
public:
    Node():last(nullptr), next(nullptr) 
    {   
    }   

    ~Node(){}

public:
    const SubNode * getLast();
    const SubNode * getNext();
    void setLast(SubNode* setLast);
    void setNext(SubNode* setNext);

protected:
    SubNode *last;
    SubNode *next;
};

template<typename SubNode>
const SubNode *Node<SubNode>::getLast()
{
    return last;
}

template<typename SubNode>
const SubNode *Node<SubNode>::getNext()
{
    return next;
}

template<typename SubNode>
void Node<SubNode>::setLast(SubNode *const _last)
{
    last = _last;
}

template<typename SubNode>
void Node<SubNode>::setNext(SubNode *const _next)
{
    next = _next;
    //_next -> setLast(this); 這條語句是不合法的,因為this指標並不能轉化為子類指標。
    //因為在基類中的this,僅程式碼基類自己,而不代表子類。
}

#endif

    程式碼還是很好懂的,下面的測試檔案:

#include"Node.h"

class A: public Node<A>
{
};

int main()
{
    A a;
    A b;
    a.setNext(&b);
    a.setLast(&b);
    b.setNext(&a);
    b.setLast(&a);
    const A *c = a.getLast();
    return 0;
} 

    優缺點比較:優點在於,省去了定義節點類的麻煩,省去了有關next last指標及相關程式碼,但有一點問題在於,如果是正常定義一個節點類,那麼成員函式setNext()我會這樣寫:

void Node::setNext(const Node *_next)
{
    next = _next;
    _next->setLast(this);
}

    別小看這一行程式碼,這一行程式碼可以幫我們省下很多東西:

//如果a指向一個連結串列中的元素,此時如果你想把a指向的Node從連結串列中移除,那麼你需要:
a->getLast()->setNext(a->getNext());
a->getNext()->setLast(a->getLast());

    發現問題了嗎?程式碼量翻倍了,如果我們能在setNext成員函式中加上一行程式碼,那麼之後每一次我們設定next節點時都可以少寫一行程式碼,反之,我們只能像上面這樣多寫一行程式碼。別小看這一行,一個大專案中,如果要多次設定next,那麼程式碼會變得很多。而且這兩行程式碼是很容易寫錯的,因為都有set get Last Next這樣的字元,一不小心極易出錯。

    要解決這個問題,可能還要寫一個管理類的模板,這樣,讓寫兩行差不多程式碼這樣的工作只做一次,其它類只要使用或繼承這個模板即可(當然這只是一個設想,尚未實現出來;) ) 。

    一般來說,如果不使用模板,那麼Node基類會有很大的限制,甚至幾乎不能用,因為你使用getNext或getLast得到的都是父類的指標,當然,你可以對它進行轉換,但轉換是C++中不推薦的一種做法。

    而使用模板後,我們可以直接通過基類的函式得到子類的指標。多high哦 ;)

    然而我不確定這種程式碼是好還是不好,看起來它帶來了便利,但實際上在父類中使用子類可能會帶來問題。不過對於這種Node,可能沒什麼影響吧,姑妄用之。