首页 > 代码库 > C++ Primer 学习笔记_82_模板与泛型编程 --类模板成员[续2]

C++ Primer 学习笔记_82_模板与泛型编程 --类模板成员[续2]

模板与泛型编程

--类模板成员[2]

六、完整的Queue

Queue的完整定义:


template <typename Type> class Queue;

template <typename Type>
ostream &operator<<(ostream &,const Queue<Type> &);

template <typename Type> class QueueItem
{
    friend class Queue<Type>;
    friend ostream &
    operator<< <Type>(ostream &,const Queue<Type> &);

    QueueItem(const Type &t):item(t),next(0) {}
    Type item;
    QueueItem *next;
};

template <typename Type> class Queue
{
    friend ostream &
    operator<< <Type>(ostream &,const Queue<Type> &);
public:
    Queue():head(0),tail(0) {}

    template <typename Iter>
    Queue(Iter beg,Iter end):head(0),tail(0)
    {
        copy_elems(beg,end);
    }
    Queue(const Queue &Q):head(0),tail(0)
    {
        copy_elems(Q);
    }

    Queue &operator=(const Queue &);
    ~Queue()
    {
        destroy();
    }

    template <typename Iter>
    void assign(Iter,Iter);

    Type &front()
    {
        return head -> item;
    }
    const Type &front() const
    {
        return head -> item;
    }

    void push(const Type &);
    void pop();
    bool empty() const
    {
        return head == 0;
    }

private:
    QueueItem<Type> *head;
    QueueItem<Type> *tail;

    void destroy();
    void copy_elems(const Queue &);
    template <typename Iter>
    void copy_elems(Iter,Iter);
};

#include “Queue.cpp”


//P559 习题16.43 + P551习题16.34
template <typename Type> class List;
template <typename Type> class ListItem
{
    friend class List<Type>;

    ListItem(Type &t):item(t),next(0) {}
    Type item;
    ListItem *next;
};

template <typename Type> class List
{
public:
    List():front(0),end(0) {}
    List(const List &rhs):front(0),end(0)
    {
        copy_elems(rhs);
    }
    template <class Iter>
    List(Iter first,Iter last):front(first),end(last)
    {
        copy_elems(first,last);
    }
    List &operator=(const List &rhs);
    ~List()
    {
        destroy();
    }

    void insert(ListItem<Type> *ptr,Type &value);
    void del(ListItem<Type> *ptr);
    ListItem<Type> *find(const Type &value);

    ListItem<Type> *first() const
    {
        return front;
    }
    ListItem<Type> *last() const
    {
        return end;
    }

    bool empty() const
    {
        return front == 0;
    }

    Type &getElem(ListItem<Type> *ptr)
    {
        return ptr -> item;
    }

    template <class Iter>
    void assign(Iter,Iter);

private:
    ListItem<Type> *front,*end;

    void destroy();
    void copy_elems(List &);
    template <class Iter>
    void copy_elems(Iter,Iter);
};

template <typename Type>
void List<Type>::destroy()
{
    while (!empty())
        del(front);
}

template <typename Type>
void List<Type>::del(ListItem<Type> *ptr)
{
    ListItem<Type> *p = front;

    while (p != 0 && p != ptr && p -> next != ptr)
    {
        p = p -> next;
    }

    if (p != 0)
    {
        if (p == ptr)
        {
            front = ptr -> next;
        }
        else
        {
            p -> next = ptr -> next;
        }
        if (ptr == end)
        {
            end = ptr -> next;
        }
        delete ptr;
    }
    else
    {
        throw out_of_range("no such element");
    }
}

template <typename Type>
void List<Type>::insert(ListItem<Type> *ptr,Type &val)
{
    ListItem<Type> *pt = new ListItem<Type>(val);

    if (empty())
    {
        front = pt;
    }
    else
    {
        pt -> next = ptr -> next;
        ptr -> next = pt;
    }

    if (ptr == end)
    {
        end = pt;
    }
}

template <typename Type>
void List<Type>::copy_elems(List<Type> &rhs)
{
    for (ListItem<Type> *pt = rhs.front; pt ; pt = pt -> next)
    {
        insert(end,pt -> item);
    }
}

template <class Type> template <typename Iter>
void List<Type>::copy_elems(Iter first,Iter last)
{
    while (first != last)
    {
        insert(end,first -> item);
        first = first -> next;
    }
    insert(end,first -> item);
}


template <typename Type>
List<Type> &List<Type>::operator=(const List<Type> &rhs)
{
    destroy();
    copy_elems(rhs);
}

template <typename Type>
ListItem<Type> *List<Type>::find(const Type &value)
{
    ListItem<Type> *pt = front;

    while (pt && pt -> item != value)
    {
        pt = pt -> next;
    }

    return pt;
}

template <class Type> template <typename Iter>
void List<Type>::assign(Iter first,Iter last)
{
    destroy();
    copy_elems(first,last);
}

//习题16.44
template <class Type> class Queue;
template <typename Type>
ostream &operator<<(ostream &os,const Queue<Type> &);

template <class Type> class Queue
{
    friend ostream &operator<< <Type>(ostream &os,const Queue<Type> &);
public:
    Queue() {}
    template <typename Iter>
    Queue(Iter beg,Iter end):items(beg,end) {}

    template <typename Iter>
    void assign(Iter beg,Iter end)
    {
        items.assign(beg,end);
    }

    Type &front()
    {
        return items.front();
    }
    const Type &front() const
    {
        return items.front();
    }

    void push(const Type &t)
    {
        items.push_back(t);
    }

    void pop()
    {
        items.erase(items.begin());
    }

    bool empty() const
    {
        return items.empty();
    }

private:
    list<Type> items;
};



七、类模板的static成员

类模板可以像任意其他类一样声明static成员。

template <class T> class Foo
{
public:
    static std::size_t count()
    {
        return ctr;
    }

private:
    static std::size_t ctr;
};

定义了名为Foo的类模板,它有一个名为countpublicstatic成员函数和一个名为ctrprivatestatic 数据成员。

Foo类的每个实例化[谨记:不是每个对象]都有自己的static成员:

    Foo<int> fi,fi2,fi3;

    Foo<string> fs;

每个实例化表示截然不同的类型,所以给定实例化所有对象都共享一个static成员。因此,Foo<int>类型的任意对象共享同一static成员 ctr,Foo<string> 类型的对象共享另一个不同的ctr成员。



1、使用类模板的static成员

通常,可以通过类类型的对象访问static成员或者使用作用域操作符直接访问static成员。当然,当试图通过类使用static成员的时候,必须引用实际的实例化:

    Foo<int> fi,fi2;
    size_t ct = Foo<int>::count();
    ct = fi.count();
    ct = fi2.count();
    ct = Foo::count();  //Error:不知道运用哪个实例化

注:static成员函数只有在程序中使用时才进行实例化



2、定义static成员

像使用任意其他static数据成员一样,必须在类外部出现数据成员的定义。在类模板含有static成员的情况下,成员定义必须指出它是类模板的成员:

template <typename Type>
std::size_t Foo<Type>::ctr = 0;


static数据成员的名字以Foo<T>::为前缀,表示成员属于类模板Foo