zoukankan      html  css  js  c++  java
  • C++STL

    类的成员变量,成员函数,成员类型,以及基类中如果包含参数化的类型,那么该类就是一个类模板
     
    1.定义
    template<typename 类型形参1, typename 类型形参2,...>
    class 类模板名[:基类]{
      成员变量
      成员函数
      成员类型
    };
     
    2.使用
    类模板名<类型实参1,类型实参2,...> 对象;
    类模板名<类型实参1,类型实参2,...> &引用 = 对象;
    类模板名<类型实参1,类型实参2,...> *指针 = &对象;
    注意: 类模板不能隐式推断,必须显示致命类型实参.
     
    3.两步实例化
    |<------编译期----->|  |<-----运行期----->|        
    类模板 - 实例化 ----> 类 - 实例化 ----> 对象
        编译器      处理器
    只有当调用成员函数的时候编译器才做类型检查
    #include <iostream>
    using namespace std;
    
    template<typename T> class Comparator {
    public:
        Comparator (T x, T y) :m_x (x), m_y (y) {}
        T min (void) const {return m_x < m_y ? m_x : m_y;}
        T max (void) const {return m_x < m_y ? m_y : m_x;}
        void foo (void) const {cout << "foo" << endl;}
    private:
        T m_x, m_y;
    };
    
    class Integer {
    public:
        Integer (int arg = 0) : m_var (arg) {}
        bool operator< (Integer const& rhs) const{
            return m_var < rhs.m_var;
        }
        friend ostream& operator<< (ostream& os,Integer const& i) {
            return os << i.m_var;
        }
    private:
        int m_var;
    };
    int main (void) {
        int a = 123, b = 456;
        Comparator<int> ci (a, b);
        cout << ci.min () << ' ' << ci.max () << endl;
        double c = 1.3, d = 4.6;
        Comparator<double> cd (c, d);
        cout << cd.min () << ' ' << cd.max () << endl;
        string e = "hello", f = "world";
        Comparator<string> cs (e, f);
        cout << cs.min () << ' ' << cs.max () << endl;
        Comparator<Integer> cn (a, b);
        cout << cn.min () << ' ' << cn.max ()<< endl;
        return 0;
    }
     
    4.类型参数
    (1)类模板中,所有的成员函数(无论其是否使用类型参数)都是函数模板, 都要延迟编译(即在编译看到调用该函数时编译),因此只有那些被调用的成员函数才会被实例化.
    (2)某些类型虽然没有提供该类模板所需要的全部功能,但照样可以实例化该模板,只要不直接或间接调用那些依赖于为提供功能的成员函数即可.
     
    5.类模板的静态成员变量
    (1)非模板: 静态成员变量是类的一部分,一个类只有一份.
          普通成员变量是对象的一部分,每个对象都有一份
    (2)类模板:静态成员变量既不是一个模板一份实例,也不是一个对象一份实例,而是在该类模板的每个实例化类中都有一份独立的实例,且为该实例化类所创建的每个对象所共享
    #include <iostream>
    using namespace std;
    template<typename T> class A {
    public:
        void paddr (void) const {
            cout << "非静:" << &m_var << ",静态:" << &s_var << endl;
        }
    private:
        int m_var;
        static int s_var;
    };
    template<typename T> int A<T>::s_var;
    int main (void) {
        A<int> a, b;
        A<double> c, d;
        a.paddr ();
        b.paddr ();
        c.paddr ();
        d.paddr ();
        return 0;
    }
    6.递归实例化
    用一个类模板的实例化类型实例化该类模板自身
    构建在空间上具有递归特征的复合结构,如:多维数组,二叉树等等
    template<typename T> class Array{..};
    template<typename T> class list{...};
    template<typename T> class Tree{...};
     
    Array<Array<int> > 二维数组
    Array<List<int> >  链表数组
    List<Array<int> >  数组链表
    List<List<int> >   二维链表      ====>通过哈希值放姓名
    Tree<List<Array<int> > > 数组链表树
     
    7.特化/特例化
    当一个类模板的通用实现无法满足某些特殊类型的需要,或者虽然可以满足需要,但是性能不佳,这时可以编写针对该特殊类型的特殊实现,这就叫类模板的特例化
    (1)完全特化:针对全部类型参数所做的特化 ====>用的比较多
    全类特化:用特定类型替换类型参数,把整个类模板重写一遍
    成员特化:只重写类模板中部分与特化类型相关的成员函数
    #include <iostream>
    #include <cstring>
    using namespace std;
    // 通用版本
    template<typename T> T max (T x, T y) {
        return x < y ? y : x;
    }
    // 针对字符指针类型的重载版本
    char* max (char* x, char* y) {
        return strcmp (x, y) < 0 ? y : x;
    }
    // 通用版本
    template<typename T> class Comparator {
    public:
        Comparator (T x, T y) : m_x (x), m_y (y) {}
        T max (void) const {
            return m_x < m_y ? m_y : m_x;
        }
        /*
        char* max (void) const {
            return strcmp (m_x, m_y) < 0 ? m_y : m_x;
        }
        */
    private:
        T m_x, m_y;
    };
    // 针对字符指针类型的特化版本
    /*
    template<>
    class Comparator<char*> {
    public:
        Comparator (char* x, char* y) : m_x (x), m_y (y) {}
        char* max (void) const {
            return strcmp (m_x, m_y) < 0 ? m_y : m_x;
        }
    private:
        char* m_x, *m_y;
    };
    */
    template<>
    char* Comparator<char*>::max (void) const {
        return strcmp (m_x, m_y) < 0 ? m_y : m_x;
    }
    int main (void) {
        int a = 123, b = 456;
        cout << ::max (a, b) << endl;
        char c[] = "hello", d[] = "world";
        cout << ::max (c, d) << endl;
        /*
        cout << ::max<string> (c, d) << endl;
        cout << ::max (string (c), string (d)) << endl;
        */
        Comparator<int> ci (a, b);
        cout << ci.max () << endl;
        Comparator<char*> cs (c, d);
        cout << cs.max () << endl;
        return 0;
    }
     
    (2)局部特化(偏特化)
    #include <iostream>
    using namespace std;
    // 通用版本
    template<typename A, typename B> class X {
    public:
        X (void) {cout << "X<A,B>" << endl;}
    private:
        A m_a;
        B m_b;
    };
    // 完全特化
    template<> class X<int, short> {
    public:
        X (void) {cout << "X<int,short>" << endl;}
    private:
        int m_a;
        short m_b;
    };
    // 局部特化
    template<typename A> class X<A, short> {
    public:
        X (void) {cout << "X<A,short>" << endl;}
    private:
        A m_a;
        short m_b;
    };
    template<typename A> class X<A, A> {
    public:
        X (void) {cout << "X<A,A>" << endl;}
    private:
        A m_a;
        A m_b;
    };
    template<typename A> class X<A, A*> {
    public:
        X (void) {cout << "X<A,A*>" << endl;}
    private:
        A m_a;
        A* m_b;
    };
    template<typename A, typename B> class X<A*, B*> {
    public:
        X (void) {cout << "X<A*,B*>" << endl;}
    private:
        A* m_a;
        B* m_b;
    };
    template<typename A> class X<A*, A*> {
    public:
        X (void) {cout << "X<A*,A*>" << endl;}
    private:
        A* m_a;
        A* m_b;
    };
    int main (void) {
        // 选择顺序:完全特化>局部特化>通用版本
        X<int, short> x1;
        X<double, short> x2;
        X<char, short> x3;
        X<int, double> x4;
        X<int, int> x5;
        X<double, double> x6;
        X<int, int*> x7;
        X<double, double*> x8;
        X<int*, double*> x9;
        X<short**, char*****> x10;
        X<int*, int*> x11;
        return 0;
    }
    8.智能指针
    (1)利用局部对象的析构函数销毁对象
    (2)通过操作符重载用智能指针来模拟平凡指针的用法
    (3)通过类型参数繁星花所维护的堆对象
    (4)通过转移语义避免浅拷贝和深拷贝的矛盾
    (5)通过局部特化来区分单个对象个对象数组 ==>>两种的释放方式不同
    c++11一般不推荐使用auto_ptr, 而是代之以smart_ptr,这才是真正的智能指针.
    智能指针的实现:
    #include <errno.h>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <memory>
    using namespace std;
    class A {
    public:
        A (void) {cout << "A构造:" << this << "->" << sizeof (*this) << endl;}
        ~A (void) {cout << "A析构:" << this << "->" << sizeof (*this) << endl;}
        void print (size_t i) const {cout << m_data[i] << endl;}
        int m_data[1024];
    };
    template<typename T> class AutoPtr {
    public:
        AutoPtr (T* p = NULL) : m_p (p) {}
        AutoPtr (AutoPtr& that) : m_p (that.release ()) {}
        AutoPtr& operator= (AutoPtr& rhs) {
            if (&rhs != this)
                reset (rhs.release ());
            return *this;
        }
        ~AutoPtr (void) { delete m_p; }
        T& operator* (void) const { return *m_p; }
        T* operator-> (void) const { return &**this; }
    private:
        T* release (void) {
            T* p = m_p;
            m_p = NULL;
            return p;
        }
        void reset (T* p) {
            if (p != m_p) {
                delete m_p;
                m_p = p;
            }
        }
        T* m_p;
    };
    template<typename T> class AutoPtr<T[]> {
    public:
        AutoPtr (T* p = NULL) : m_p (p) {}
        AutoPtr (AutoPtr& that) : m_p (that.release ()) {}
        AutoPtr& operator= (AutoPtr& rhs) {
            if (&rhs != this)
                reset (rhs.release ());
            return *this;
        }
        ~AutoPtr (void) { delete[] m_p; }
        T& operator* (void) const { return *m_p; }
        T* operator-> (void) const { return &**this; }
    private:
        T* release (void) {
            T* p = m_p;
            m_p = NULL;
            return p;
        }
        void reset (T* p) {
            if (p != m_p) {
                delete[] m_p;
                m_p = p;
            }
        }
        T* m_p;
    };
    void foo (void) {
        /*
        A a, *pa = &a;
        pa->m_data[0] = 12345;
        (*pa).print (0);
        */
    //  A* pa = new A;
        AutoPtr<A> pa (new A);
        pa->m_data[0] = 12345;
    //  pa.operator->()->m_data[0] = 12345;
        (*pa).print (0);
    //  pa.operator*().print (0);
        AutoPtr<A> pb = pa; // 拷贝构造
        ++pb->m_data[0];
        (*pb).print (0); // 12346
        AutoPtr<A> pc (new A);
        pc->m_data[0] = 22222;
        pb = pc; // 拷贝赋值
        ++pb->m_data[0];
        (*pb).print (0); // 12346
        FILE* fp = fopen ("none", "r");
        if (! fp) {
    //      delete pa;
            throw errno;
        }
        // ...
        fclose (fp);
    //  delete pa;
    }
    int main (void) {
        /*
        try {
            foo ();
        }
        catch (int ex) {
            cout << strerror (ex) << endl;
            return -1;
        }
        cout << "成功!" << endl;
        */
    //  AutoPtr<A[]> pa (new A[3]);
        AutoPtr<A> pa (new A);
        /*
        auto_ptr<T>
        */
        return 0;
    }
     
    关于智能指针后续再单独拿出来总结一下, 还不是很清楚....
     
  • 相关阅读:
    23种设计模式(3)-原型模式
    23种设计模式(4)-生成器模式
    优秀程序员应具备的15个特性
    23种设计模式(5)-适配器模式
    23种设计模式(6)-装饰者模式
    23种设计模式(7)-代理模式
    SSH框架面试题集锦
    List,Set和Map详解及其区别和他们分别适用的场景
    (转) 网页浏览速度慢的排查原因
    (转)局域网的某个机器无法上网,的排错思路
  • 原文地址:https://www.cnblogs.com/niie9/p/6158810.html
Copyright © 2011-2022 走看看