类的成员变量,成员函数,成员类型,以及基类中如果包含参数化的类型,那么该类就是一个类模板
 
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. react入门(1)

    这篇文章也不能算教程咯,就算是自己学习整理的笔记把. 关于react一些相关的简介.优势之类的,随便百度一下一大堆,我就不多说了,可以去官网(http://reactjs.cn/)看一下. 这片主要讲 ...

  2. mysql null值处理详细说明

    在讲null之前,我们先看一个例子 表数据如下: 3306>select * from t1; +------+-------+ | id | name | +------+-------+ | ...

  3. FreeRTOS 中断优先级嵌套错误引发HardFault异常解决(转)

      最近在使用FreeRTOS的时候,突然发现程序在运行了几分钟之后所有的任务都不再调用了,只有几个中断能正常使用,看来是系统挂掉了,连续测试了几次想找出问题,可是这个真的有点不知所措.      我 ...

  4. Visual Studio.NET单选题

     在Visual Studio.NET窗口中,在__________窗口中可以察看当前项目的类和类型的层次信息. A. 解决方案资源管理器 B. 类视图 C. 资源视图 D. 属性 在线答题:http ...

  5. 尝试加载 Oracle 客户端库时引发 BadImageFormatException

    尝试加载 Oracle 客户端库时引发 BadImageFormatException 工程师给计算机诊断,就像医生给病人诊断一样,很多同样的症状,可能是由多种截然不同的原因导致的.   最近进行C# ...

  6. 《c# 从入门经典》 (第6版) - c# 简介

    1,.NET Framework:是开发平台,包含两大部分: ①庞大的代码库(类库),可以在客户语言(C#,VB)中来使用这些代码 ②Common Language Runtime,负责管理应用程序的 ...

  7. 微信扫码i支付~官方DEMO的坑

    返回目录 之前写过关于微信支付那些坑的文章(<微信JSApi支付~集成到MVC环境后的最后一个坑(网上没有这种解决方案)>,<微信JSApi支付~坑和如何填坑>),下面说一下微 ...

  8. jquery css属性练习

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. hadoop基本命令

    1,hadoop job -list           列出Jobtracer上所有的作业 2,hadoop job -kill 任务    杀掉hadoop正在运行的任务 3,hadoop fs ...

  10. 使用MyEclipse中servlet对SQL Server 2008的CRUD

    1.在MyEclipse下建立Web Project,找到根目录建立Database文件夹和Doc文件夹,Database用于保存数据库信息,Doc用于保存数据库表信息. 2.打开SQL Server ...