C++ Primer第五版之第16章 模板与泛型编程

第16章 模板与泛型编程

定义模板

函数模板

  • 模板定义以关键字template开始,后跟一个模板参数列表(是一个逗号分隔的一个或多个模板参数的列表),用<>包围起来。
  • 在模板定义中,模板参数列表不能为空。
template 
int compare(const T &v1, const T &v2)
{
    if (v1 < v2)   return -1;
    if (v2 < v1)   return 1;
    return 0;
}
  • 实例化函数模板:调用template时,编译器使用实参的类型来确定绑定到模板参数T的类型,之后编译器利用推断出来的模板参数来实例化一个特定版本的函数。
  •  模板类型参数:使用关键字class或typename来指定模板类型参数(常使用typename)。
template
calc(const T&, const U&);
  • 非类型参数:表示一个值而非一个类型,通过一个特定的类型名而非关键字class或typename来指定
    • 当一个模板被实例化时,非类型参数被一个用户提供的或编译器推断出来的值所代替,这些值必须是常量表达式。
    • 非类型模板参数的模板实参必须是常量表达式.
template 
int compare(const char (&p1)[N], const char (&p2)[M])
{
    return strcmp(p1,p2);
}
compare("Hi", "Mom");
  • 函数模板可以声明为inline或constexpr的,inline或constexpr说明符放在模板参数列表之后,返回类型之前
  • 模板编译:当我们实例化出模板的一个特定版本时,编译器才会生成代码; 函数模板和类模板成员函数的定义通常放在头文件中。

类模板

  •  用来生成类的蓝图,与函数模板不同之处在于编译器不能为类模板推断模板参数类型,而需要显式提供参数类型。
template
class Blob {
public:
    //...
private:
    std::shared_ptr> data;
};
Blob ia;
  • 当使用一个类模板时,必须提供额外信息,这些额外信息是显示模板实参列表,它们被绑定到模板参数,编译器使用这些模板实参来实例化出特定的类。
  • 一个类模板的每个实例都形成一个独立的类。实例化出来的Blob与其他的Blob类型都没有关联,也不会对任何其他Blob类型的成员有特殊访问权限
  • 一个类模板中的代码如果使用了另外一个模板,通常不将一个实例类型的名字用作其模板实参,相反将模板自己的参数当作被使用模板的实参。
//在模板作用于中引用模板类型
std::shared_ptr> data;    //T为Blob模板的参数
  • 在类外定义一个成员函数时,必须以关键字template开始,后接类模板参数列表;另外还必须说明成员属于哪个类。
template 
void Blob::check(size_type i, const string &msg) const
{
    if (i >= data->size())
        throw out_of_range(msg);
}
template
T& Blob::operator[](size_t i){
	check(i, "subscript out of range"); //检查下标
	return(*data)[i];
}
  • 默认情况下,对于一个实例化了的类模板,其成员只有在使用时才被实例化。
  • 当我们使用一个类模板类型时必须提供模板实参,但在类模板自己的作用域中我们可以直接使用模板名而不提供实参。
  • 当我们在类模板外定一起成员时,必须记住我们只有在遇到类名时才表示进入类的作用域。
template
BlobPtr BlobPtr::operator++(int);

类模板和友元

  • 如果类模板包含一个非模板友元,则友元被授权可以访问所有模板实例;如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例。
  • 进行友元声明必须首先前置声明模板本身。
//前置声明,在Blob中声明友元所需
template  class BlobPtr;
template  class Blob;
template 
    bool operator==(const Blob&, const Blob&);

template  class Blob {
        //每个Blob实例将访问权限授予用相同类型实例化的BlobPtr和相等运算符
        friend class BlobPtr;
        friend bool operator==
                (const Blob&, const Blob&);
};
  • 可以定义typedef来引用实例化的类,还可以使用using来声明类型别名。
typedef Blob StrBlob;    //引用实例化的Blob类

template  using twin = pair;   //twin为pair的别名
twin authors;     //authors是一个pair

类模板的static成员

  • 每一个类模版的实例都有自己的static成员实例,但对于给定的类型,该static成员实例共享;类模版的static成员有且仅有一个定义。

你可能感兴趣的:(C++,Primer学习之路)