C++学习之模板应用 ---array、smartptr、stack

有array(数组)、smartptr(智能指针)、stack(栈);

一、array:

1、我们实现了指针访问和下标访问。C++中指针访问常用迭代器来代替。

2、这里我们也揭示了 size_type、iterator、[] 、begin()、end()、size()的真实面目;

Array.hpp

 1 #ifndef ARRAY_H_
 2 #define ARRAY_H_
 3 //Arrar.hpp
 4 #include <stddef.h>
 5 template <typename T, int MAXSIZE>
 6 class Array
 7 {
 8     public:
 9         //我们假设T为int型
10         typedef T value_type;  //int
11         typedef T *iterator;   // int*->将int* 重定义为interator
12         typedef const T* const_iterator;
13         typedef T &reference; //int& -->将int& 重定义为reference
14         typedef const T& const_reference;
15         typedef size_t size_type;//size_type常用于vector<int>::size_type 下表访问
16  
17         iterator begin()//begin返回的是首地址
18         { return elems_; }
19         const_iterator begin()const
20         { return elems_; }
21 
22         iterator end()//end返回的是末尾元素的下个地址
23         { return elems_+ MAXSIZE; }
24         const_iterator end()const
25         { return elems_+ MAXSIZE; }
26 
27         reference operator[](size_type index)//下标访问返回的是对本身的引用
28         { return elems_[index]; }
29         const_reference operator[](size_type index)const
30         { return elems_[index]; }
31 
32         size_type size()const  //int->元素个数
33         { return MAXSIZE;}
34     private:
35         T elems_[MAXSIZE];
36 };
37 
38 #endif

main.cpp:

 1 #include "Array.hpp"
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 template <typename T>
 7 void print(const T &t)
 8 {
 9     for(typename T::const_iterator it = t.begin(); //迭代器实现打印
10          it!= t.end();
11          it++)
12     {
13         cout << *it << " ";
14     }
15     cout << endl;
16 }
17 
18 int main(int argc, const char *argv[])
19 {
20     Array<int, 20> arr;
21 
22     for(Array<int, 20>::size_type ix =0;   //下标实现初始化
23         ix != arr.size();
24         ix ++)
25     {
26         arr[ix] = ix;
27     }
28     
29     print(arr);
30     
31     Array<int, 20>::const_iterator it=std::find(arr.begin(), arr.end(), 15);
32     cout << *it << endl; //标准库中的find函数
33 
34     return 0;
35 }

二、智能指针:
这里我们实现了指针的一些操作, 如解引用操作符,->操作符、指针的复制与赋值。

代码如下:

SmartPtr.hpp

 1 #ifndef SMARTPTR_H_
 2 #define SMARTPTR_H_
 3 
 4 #include <stddef.h>
 5 
 6 template <typename T>
 7 class SmartPtr
 8 {
 9     public:
10         SmartPtr(T *ptr= NULL ); //如果没有提供ptr的值,编译器会将其默认为NULL
11         ~SmartPtr();
12 
13         T &operator*() //解引用操作返回的是本身值的引用
14         { return *ptr_; }
15         const T &operator*()const
16         { return *ptr_; }
17         
18         T *operator->() //->操作 返回的是 指针本身;
19         { return ptr_;}
20         const T *operator->()const
21         { return ptr_;}
22 
23         void resetPtr(T *ptr = NULL); //将 指针重置
24         const T *getPtr()const //获取该指针
25         { return ptr_; }
26 
27     private:
28         //这里我们禁用了智能指针的复制和赋值能力
29         SmartPtr(const SmartPtr&); 
30         SmartPtr &operator=(const SmartPtr&);
31 
32         T *ptr_;  
33 };
34 
35 template <typename T>
36 SmartPtr<T>::SmartPtr(T *ptr )
37     :ptr_(ptr)
38 { }
39 
40 template <typename T>
41 SmartPtr<T>::~SmartPtr()
42 { delete ptr_; } 
43 
44 template <typename T>
45 void SmartPtr<T>::resetPtr(T *ptr )
46 {
47     if(ptr_ == ptr) //如果把自己本身赋值给自己,则直接返回
48         return;
49     delete ptr_;
50     ptr_ = ptr ;
51 }
52 
53 #endif

main.cpp:

 1 #include "SmartPtr.hpp"
 2 #include <iostream>
 3 using namespace std;
 4 
 5 class Test
 6 {
 7     public:
 8 
 9         Test() {cout << "construct" << endl; }
10         ~Test(){cout << "~construct" << endl; }
11 };
12 
13 int main(int argc, const char *argv[])
14 {
15     SmartPtr<Test> sp(new Test); 
16 
17     return 0;
18 }


三、Stack 及其特化:

1、这里我们揭示了Stack 的 pop、push、top、empty操作;

2、对于一些特殊的类型,如 const char*(C风格的字符串),当我们用push函数时,总会出现一些问题,原因在于:

push函数复制给定值以创建 stack中的新元素(值拷贝),而默认情况下,复制C 风格字符串只会复制其指针,不会复制字符串(衰退【decay】),这时复制指针将会出现共享指针在其他环境中会出现的所有问题(如重复析构),最严重的是,若指针指向动态内存,用户就有可能删除指针所指的数组。

 1 //Stack.hpp
 2 #ifndef STACK_H_
 3 #define STACK_H_
 4 
 5 #include <vector>
 6 #include <stdexcept>
 7 
 8 //Stack-----------------------
 9 template <typename T>
10 class Stack
11 {
12     public:
13         void push(const T &t);
14         void pop();
15         T top()const; 
16 
17         bool empty()const
18         { return elems_.empty(); }
19     private:
20         std::vector<T> elems_;
21 };
22 
23 template <typename T>
24 void Stack<T>::push(const T &t)
25 {
26     elems_.push_back(t);
27 }
28 
29 template <typename T>
30 void Stack<T>::pop()
31 {
32     if( !elems_.empty() )
33         elems_.pop_back();
34     else
35         throw std::out_of_range("out of range");
36 }
37 
38 template <typename T>
39 T Stack<T>::top()const 
40 {
41     if( !elems_.empty() )
42         return elems_.back();
43     else
44         throw std::out_of_range("out of range");
45 }
46 //----------------------------
47 
48 //特化------------------
49 template <>
50 class Stack<const char*>
51 {
52     public:
53         void push(const char *);
54         void pop();
55         const std::string top()const;  
56        //注意上面的函数返回的是string,为了避免管理字符数组char[]
57         bool empty()const
58         { return elems_.empty(); }
59     private:
60         std::vector<std::string> elems_; //通过这一数据元素实现以上各个功能
61 };
62 
63 void Stack<const char*>::push(const char*t)
64 {
65     elems_.push_back(t);
66 }
67 
68 void Stack<const char*>::pop()
69 {
70     if( !elems_.empty() )
71         elems_.pop_back();
72     else
73         throw std::out_of_range("out of range");
74 }
75 
76 const std::string Stack<const char*>::top()const 
77 {
78     if( !elems_.empty() )
79         return elems_.back();
80     else
81         throw std::out_of_range("out of range");
82 }
83 //----------------
84 
85 #endif

main.cpp

//main.cpp
#include "Stack.hpp"
#include <iostream>
using namespace std;

int main(int argc, const char *argv[])
{
    try
    {
        const char *s1 = "foo";
        Stack<const char *> st;
        
        st.push(s1);
        st.push("bar");
        
        cout << st.top() << endl;
        st.pop();

        cout << st.top() << endl;
        st.pop();

    }
    catch(exception &e)
    {
        cout << e.what()<< endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xfxu/p/4003740.html