您的位置:首页 > 编程语言 > C语言/C++

从零开始学C++之模板(二):类模板、Stack的类模板实现(自定义链栈方式,自定义数组方式)

2013-07-21 12:49 716 查看
一、类模板

类模板:将类定义中的数据类型参数化

类模板实际上是函数模板的推广,可以用相同的类模板来组建任意类型的对象集合

(一)、类模板的定义

template  <类型形参表>

class  <类名>

{     //类说明体  };

template  <类型形参表>

<返回类型> <类名> <类型名表>::<成员函数1>(形参表)

{     //成员函数定义体  }

template  <类型形参表>

<返回类型> <类名> <类型名表>::<成员函数2>(形参表)

{     //成员函数定义体  }



template  <类型形参表>

<返回类型> <类名> <类型名表>::<成员函数n>(形参表)

{     //成员函数定义体  }

(二)、使用类模板

类模板的实例化:用具体的数据类型替换模板的参数以得到具体的类(模板类)

模板类也可以实例化为对象

用下列方式创建类模板的实例:

类名 <类型实参表>  对象名称;

对于函数模板与类模板,模板参数并不局限于类型(类类型,基本类型,模板类实例),普通值也可以作为模板参数

二、Stack类的模板实现

前面曾经分别使用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指向的下一个结点,一直找到最后的一个结点
        //故先释放最后一个结点(当然是最先压栈的结点),然后依次返回释放每一个途中的结点
    }
    cout << m_Value << " 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++编程规范
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐