1:类模板的具体实现方式:参见P689
对于Query模板类如下:
template<class type>
class Query
{
public:
void query();
private:
class QueryItem
{
public:
type getA();
type getB();
private:
type a;
type b;
};
private:
QueryItem *next;//这里不需要什么参数类型了
};
由于QueryItem属于内部模板类,可以直接使用Query的模板参数。同时作为query的私有类,不需要把Query作为QueryItem类的友元存在,只要
QueryItem提供Query的接口getA,getB就可以了。如果不如此,则把QueryItem类全部作为共有成员存在。
两个类模板(QueryItem, Query)的实例时机:上例中首先我们Query<int> QueryInt,这时候先实例化Query类模板,QueryItem没有被实例化,
只有对next成员解引用的时候才实例化QueryItem类模板。
2:成员模板 P691
成员模板分为两种:1类数据成员模板,2类函数成员模板
template<class T>
class Query
{
private:
template< class Type >
class CL<Type>
{
public:
Type m;
T n;
};
public:
template< class It>
void assign< It first, It last)
{
remove(); //call Query<T>::remove() to clear Query<T>
while (first!=last)
{
add(*first); //call Query<T>::add to set Query<T>
++first;
};
};
};
对于assign这样的成员函数中,在标准库的vector容器就用到了,例如:
int a[] = { 1, 2,3};
vector<int> vt(a[0], a[3);
其对应原型如下:vector的member function
template <class InputIterator>
void
assign(InputIterator first, InputIterator last);
Erases all elements contained in self, then inserts new elements from the range [first, last).
对于这样类成员函数模板,对类内的任意成员函数都是适用的。比如构造函数,上述的assign同构造函数形式上的差异仅仅在于名字。
类成员模板在类外的实现。
上述assign可以实现如此:
template<class T> template <class It>
void Query<T>::assign(It first, It last)
{
....
};
template<class T> template <class Type>
class Query<T>::CL<class Type>
{
....
};
16.8类模板及其编译模式 P695
类模板的实例:只有在上下文context要求类模板的完整定义时才被实例。举个例子:new的时候,或者调用成员函数的时候。在仅仅是个引用
或者指针的时候不需要类的完整定义。具体参见16.2节。
另外对于构造函数的初始化,尽量使用构造函数表达式来初始化。因为复杂类型(这里指有构造函数的类成员,如string),不要在构造函数
{}设置,因为这样会构造两次。
1:传引用
2:初始化表达式
实例化的时机:原文摘如下
针对一个特定类型而实例化类模吧不会引起“针对同一类型自动实例化类模板成员的
定义”。只有当程序需要知道成员的定义时(即如果嵌套类被使用时要求它的完整类类型
或如果调用成员函数,或如果做成员地址,或如果查看静态数据成员的值)成员才会被实
例化。
编译模式的分类:
1:包含模式。即类模板的定义都放在同一个头文件中实现,可以是作为inline函数,或者不作为inline函数,在头文件中定义。
2:分离模式:定义(实现文件)和声明(头文件)分开,这里头文件中需要增加export关键字说明。
这个关键字放在头文件中的template关键字前即可(这样整个类模板被export)。
例如: Query.h
export template < class T>
Query{...};
export关键字的作用:告诉编译器,当使用一个类模板的成员函数实例或者静态数据成员实例时,只“要求”类模板的定义。
针对单个成员的export
//--Query.h
template<class Type>
class Query
{
public:
void remove();
void add(const Type &);
};
template <class Type>
void Query<Type>::remove()
{
...
};
//--Query.cpp
#include "query.h"
temlate<class Type>
export void Query<Type>::add(..)
{
...
}
模板的显示实例申明 explicit instantiation declaration
#include "Query.h" //--这里需要提供全部的Query模板类的定义
template class Query<int>;
对于这样的申明,需要使用编译选项“抑制模板隐式实例化”来避免对同一个模板类多次申明。
16.9模板特化 P700 ~ P704
#include <iostream>
template <class Type>
class Compare
{
public:
Type max(Type a, Type b);
} ;
template<class Type>
Type Compare<Type>::max(Type a, Type b)
{
return (a>b)?a:b;
} ;
template<>
double Compare<double>::max(double a, double b)
{
return 1;
} ;
int main(int argc, char* argv[])
{
Compare<int> com;
std::cout << com.max(30,20) << std::endl;
Compare<double> com_d;
std::cout << com_d.max(4.4, 5.5) <<std::endl ;
return 0;
}
16.11 类模板的名字解析 P705
16.12 名字空间和类模板 P707
16.13 模板数组类 P709