類模板、Stack的類模板實現(自定義鏈棧方式,自定義數組方式)

1、類模板ios

類模板:將類定義中的數據類型參數化
類模板其實是函數模板的推廣,能夠用相同的類模板來組建任意類型的對象集合
編程

(一)、類模板的定義數組

template  <類型形參表>
class  <類名>
{     //類說明體  };
template  <類型形參表>
<返回類型> <類名> <類型名錶>::<成員函數1>(形參表)
{     //成員函數定義體  }
template  <類型形參表>
<返回類型> <類名> <類型名錶>::<成員函數2>(形參表)
{     //成員函數定義體  }

template  <類型形參表>
<返回類型> <類名> <類型名錶>::<成員函數n>(形參表)
{     //成員函數定義體  }
函數


(二)、使用類模板spa

類模板的實例化:用具體的數據類型替換模板的參數以獲得具體的類(模板類)
模板類也能夠實例化爲對象
用下列方式建立類模板的實例:
.net

類名 <類型實參表>  對象名稱;指針

對於函數模板與類模板,模板參數並不侷限於類型(類類型,基本類型,模板類實例),普通值也能夠做爲模板參數對象


2、Stack類的模板實現blog

前面曾經分別使用C/C++實現了一個鏈棧,棧中只能放進int類型數據,如今使用模板來從新實現Stack,能夠存放多種數據類型,分別使用自定義鏈棧方式以及自定義數組實現。內存

(一)、自定義鏈棧方式:

stack.h:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 
/*************************************************************************
> File Name: stack.h
> Author: Simba
> Mail: dameng34@163.com
> Created Time: 2012年11月03日 星期六 19時28分25秒
************************************************************************/

#include<iostream>
using namespace std;
template < class T > class Node
{
    //< >裏面是模板參數,能夠有多個,雖然T用class 聲明,但能夠是內建類型也能夠是class類型
    //模板的定義通常寫在頭文件裏
public:

    Node(T invalue): m_Value(invalue), m_Next(NULL) {}
    ~Node();

    T getValue() const
    {
        return m_Value;
    }
    void setValue(T value)
    {
        m_Value = value;
    }

    Node < T > *getNext() const
    {
        return m_Next;
    }
    void setNext(Node < T > *next)
    {
        m_Next = next;
    }

private:
    T m_Value;
    Node < T > *m_Next;
};

template < class T > Node < T >::~Node()
{
    if (m_Next)
    {
        delete m_Next;  //自動內存管理,接着找到m_Next指向的下一個結點,一直找到最後的一個結點
        //故先釋放最後一個結點(固然是最早壓棧的結點),而後依次返回釋放每個途中的結點
    }
" deleted " << endl;
}

template < class T > class Stack
{

public:
    Stack(): m_Head(NULL), m_Count(0) {}
    ~Stack()
    {
        delete m_Head;  //自動內存管理
    }
    void push(const T &t);
    T pop();
    T top() const;
    int count() const;
private:
    Node < T > *m_Head;
    int m_Count;
};

template < class T > void Stack < T >::push(const T &value)
{
    Node < T > *newNode = new Node < T > (value);
    newNode->setNext(m_Head);
    m_Head = newNode;
    ++m_Count;
}

template < class T > T Stack < T >::pop()
{
    Node < T > *popped = m_Head;
    if (m_Head != NULL)
    {

        m_Head = m_Head->getNext();
        T retval = popped->getValue();
        popped->setNext(NULL);
        delete popped;
        --m_Count;
        return retval;
    }
    return 0;
}

template < class T > inline T Stack < T >::top() const
//模板前綴template < class T >  || 函數限定符inline  函數返回值T ||
//命名空間前綴 Stack < T > //一個類型  || 函數名(函數參數)const 限定符
{
    return m_Head->getValue();

}

template < class T > inline int Stack < T >::count() const
{
    return m_Count;
}

main.cpp:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
#include "stack.h"

int main(void)
{
    Stack < int >intstack1, intstack2;

    int val;
    for (val = 0; val < 4; ++val)
    {
        intstack1.push(val);
        intstack2.push(2 * val);
    }

    while (intstack1.count())
    {
        val = intstack1.pop();
        cout << val << endl;
    }

    Stack < char >stringstack;

    stringstack.push('A');
    stringstack.push('B');
    stringstack.push('C');

    char val2;
    while (stringstack.count())
    {
        val2 = stringstack.pop();
        cout << val2 << endl;
    }
    cout << "Now intstack2 will be destructed." << endl;
    return 0;
}


能夠看到雖然intstack2 沒有pop 出元素,但程序結束時,局部對象會被析構,調用析構函數,在析構函數內delete 頭指針,順藤摸瓜一直找到最後一個節點,即首先壓棧的節點,依次返回釋放掉。


(二)、自定義數組方式

Stack2.h:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 
#ifndef _STACK2_H_
#define _STACK2_H_

#include <exception>

template <typename T, int MAX_SIZE>
class Stack2
{
public:
    Stack2();
    ~Stack2();

    void Push(const T &elem);
    void Pop();
    T &Top();
    const T &Top() const;
    bool Empty() const;
private:
    T *elems_;
    int top_;
};

template <typename T, int MAX_SIZE>
Stack2<T, MAX_SIZE>::Stack2() : top_(-1)
{
    elems_ = new T[MAX_SIZE];
}

template <typename T, int MAX_SIZE>
Stack2<T, MAX_SIZE>::~Stack2()
{
    delete[] elems_;
}

template <typename T, int MAX_SIZE>
void Stack2<T, MAX_SIZE>::Push(const T &elem)
{
    if (top_ + 1 >= MAX_SIZE)
        throw out_of_range("Stack2<>::Push() Stack2 full");

    elems_[++top_] = elem;
}

template <typename T, int MAX_SIZE>
void Stack2<T, MAX_SIZE>::Pop()
{
    if (top_ + 1 == 0)
        throw out_of_range("Stack2<>::Push() Stack2 empty");

    --top_;
}

template <typename T, int MAX_SIZE>
T &Stack2<T, MAX_SIZE>::Top()
{
    if (top_ + 1 == 0)
        throw out_of_range("Stack2<>::Push() Stack2 empty");

    return elems_[top_];
}

template <typename T, int MAX_SIZE>
const T &Stack2<T, MAX_SIZE>::Top() const
{
    if (top_ + 1 == 0)
        throw out_of_range("Stack2<>::Push() Stack2 empty");

    return elems_[top_];
}

template <typename T, int MAX_SIZE>
bool Stack2<T, MAX_SIZE>::Empty() const
{
    return top_ + 1 == 0;
}
#endif // _STACK2_H_

main.cpp:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
#include "Stack2.h"
#include <iostream>
#include<string>
using namespace std;

int main(void)
{
    Stack2<int, 5> s;
    s.Push(1);
    s.Push(2);
    s.Push(3);

    while (!s.Empty())
    {
        cout << s.Top() << endl;
        s.Pop();
    }
    return 0;
}

輸出爲 3 2 1

注意,用數組實現時pop 操做並無刪除元素的操做,只是移動了top 指針,下次push 的時候直接覆蓋便可。再者由於實現了Top 返回棧頂元素,故pop 沒有返回值。


參考:

C++ primer 第四版 Effective C++ 3rd C++編程規範

相關文章
相關標籤/搜索