首页 > 代码库 > C++STL - 类模板
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; }
关于智能指针后续再单独拿出来总结一下, 还不是很清楚....
C++STL - 类模板
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。