类的成员变量,成员函数,成员类型,以及基类中如果包含参数化的类型,那么该类就是一个类模板
 
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 () : 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) {
    , b = ;
    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;
    ;
}
 
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 ();
    ;
}
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) {
     ? 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 {
     ? m_y : m_x;
}
int main (void) {
    , b = ;
    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;
    ;
}
 
(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;
    ;
}
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;}
    ];
};
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[] = ;
//  pa.operator->()->m_data[0] = 12345;
    (*pa).print ();
//  pa.operator*().print (0);
    AutoPtr<A> pb = pa; // 拷贝构造
    ++pb->m_data[];
    (*pb).print ();
    AutoPtr<A> pc (new A);
    pc->m_data[] = ;
    pb = pc; // 拷贝赋值
    ++pb->m_data[];
    (*pb).print ();
    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>
    */
    ;
}
 
关于智能指针后续再单独拿出来总结一下, 还不是很清楚....
 

C++STL - 类模板的更多相关文章

  1. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  2. STL标准模板类

    STL,中文名标准模板库,是一套C++的标准模板类(是类!),包含一些模板类和函数,提供常用的算法和数据结构. STL分为:迭代器,容器,适配器,算法以及函数对象. --迭代器是一种检查容器内元素并遍 ...

  3. 如何导出标准模板库(STL)类的实例化和包含STL类对象数据成员的类

    本文翻译自 https://support.microsoft.com/zh-cn/help/168958/how-to-export-an-instantiation-of-a-standard-t ...

  4. 智能指针类模板(上)——STL中的智能指针

    智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...

  5. STL之template类模板

    #include <iostream> using namespace std; template<class T>//类模板 class Person{ public://构 ...

  6. STL标准模板库(简介)

    标准模板库(STL,Standard Template Library)是C++标准库的重要组成部分,包含了诸多在计算机科学领域里所常见的基本数据结构和基本算法,为广大C++程序员提供了一个可扩展的应 ...

  7. STL标准模板库介绍

    1. STL介绍 标准模板库STL是当今每个从事C++编程的人需要掌握的技术,所有很有必要总结下 本文将介绍STL并探讨它的三个主要概念:容器.迭代器.算法. STL的最大特点就是: 数据结构和算法的 ...

  8. 4.1 pair类模板

    在学习关联容器之前,首先先要了解一下STL中的pair类模板,因为关联容器的一些成员函数返回值都是pair对象,而且map 和multimap中的元素都是pair对象. 1)pair类模板定义 pai ...

  9. [Reprint] C++函数模板与类模板实例解析

    这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下   本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...

随机推荐

  1. Eclipse与Android源码中ProGuard工具的使用

    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...

  2. Redis 对比 Memcached 并在 CentOS 下进行安装配置

    了解一下 Redis Redis 是一个开源.支持网络.基于内存.键值对的 Key-Value 数据库,使用 ANSI C 编写,并提供多种语言的 API ,它几乎没有上手难度,只需要几分钟我们就能完 ...

  3. EF中的实体类型【Types of Entity in Entity】(EF基础系列篇8)

    We created EDM for existing database in the previous section. As you have learned in the previous se ...

  4. iOS面试题集锦

    一.前言部分 文中的问题多收集整理自网络,不保证100%准确,还望斟酌采纳. 1.怎样防止指针的越界使用问题? 答案: 1 .防止数组越界,必须让指针指向一个有效的内存地址, 2. 防止向一块内存中拷 ...

  5. sql count统计技巧

    select count(1) from table where columnname=value 写成 select count(case when columnname=value than 1 ...

  6. Idea创建Maven项目

  7. cessss

    [文字] 关注1啊啊啊啊啊 点击关注微信 点击关注微信2 点击关注微信3 关注2啊啊啊啊啊啊啊啊啊啊啊 关注3啊啊啊啊啊啊啊啊 关注4啊啊啊啊啊啊啊啊 关注5啊啊啊啊啊啊啊啊 关注6啊啊啊啊啊啊啊啊啊 ...

  8. 《C#微信开发系列(3)-获取接口调用凭据》

    3.0获取接口调用凭据 ①接口说明 access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.access_token的存储至少要保留 ...

  9. iOS 线程间的通信 (GCD)

    1.从网络上 下载一张图片将它显示在view上 - (void)imageDownload { dispatch_async(dispatch_get_global_queue(DISPATCH_QU ...

  10. 『SharePoint』Content Editor Webpart不能添加引用_layouts下面的文件

    好久没写了,最近没怎么学到新东西,倒是犯了一个很常见的错误,那就是试图在content editor webpart中添加位于_layouts下面的一个txt文件,虽然这个txt中只是几行简单的htm ...