类模板

来源:互联网 发布:专业书籍阅读软件 编辑:程序博客网 时间:2024/06/03 12:27

类模板(class template)是用来生成类的蓝图的。与函数模板不同的是,编译器不能为类模板推断模板参数类型。

实例化类模板
当使用一个类模板时,我们必须提供额外信息。我们现在知道这些额外信息是显式模板实参(explicit template argument)列表,它们被绑定到模板参数。编译器使用这些模板实参来实例化出特定的类。

在模板作用域中引用模板类型
类模板的名字不是一个类型名。类模板用来实例化类型,而一个实例化的类型总是包含模板参数的。
一个类模板中的代码如果使用了另一个模板,通常不将一个实际类型(或值)的名字用作其模板实参。相反的,我们通常将模板自己的参数当作被使用模板的实参。

类模板的成员函数
类模板的成员函数本身是一个普通函数。但是,类模板的每个实例都有其自己版本的成员函数。因此,类模板的成员函数具有和模板相同的模板参数。因而,定义在类模板之外的成员函数被必须以关键字template开始,后接类模板参数列表。
与往常一样,当我们在类外定义一个成员时,必须说明成员属于哪个类。而且,从一个模板生成的类的名字中必须包含其模板实参。当我们定义一个成员函数时,模板实参与模板形参相同。

类模板成员函数的实例化
默认情况下,一个类模板的成员函数只有当程序用到它时才进行实例化。
如果一个成员函数没有被使用,则它不会被实例化。

在类代码内简化模板类名的使用
当我们使用一个类模板类型时必须提供模板实参,但这一规则有一个例外。在类模板自己的作用域中,我们可以直接使用模板名而不提供实参。
当我们处于一个类模板的作用域叶时,编译器处理模板自身引用时就好像我们已经提供了与模板参数匹配的实参一样。

在类模板外使用类模板名
当我们在类模板外定义其成员时,必须记住,我们并不在类的作用域中,直到遇到类名才表示进入类的作用域。
如果不提供模板实参,则编译器将假定我们使用的类型与成员实例化所用的类型一致。
在一个类模板的作用域内,我们可以直接使用模板名而不必指定模板实参。

类模板和友元
当一个类包含一个友元声明时,类与友元各自是否是模板是相互无关的。如果一个类模板包含一个非模板友元,则友元被授权可以访问所有模板实例。如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例。

为了引用(类或函数)模板的一个特定实例,我们必须首先声明模板自身。一个模板声明包括模板参数列表。

通用和特定的模板友好关系
一个类也可以将另一个模板的每个实例都声明为自己的友元,或者限定特定的实例为友元。
为了让所有实例成为友元,友元声明中必须使用与类模板本身不同的模板参数。

令模板自己的类型参数成为友元
要新标准中,我们可以将模板类型参数声明为友元:

template <typename Type>class Bar{    // 将访问权限授予用来实例化Bar的类型    friend Type;    ...};

值得注意的是,虽然友元通常来说应该是一个类或是一个函数,但我们完全可以用一个内置类型来实例化Bar。这种与内置类型的友好关系是允许的,以便我们能用内置类型来实例化Bar这样的类。

模板类型别名
类模板的一个实例定义了一个类类型,与任何其他类类型一样,我们可以定义一个typedef来引用实例化的类。但由于模板不是一个类型,我们不能定义一个typedef引用一个模板。
但是,新标准允许我们为类模板定义一个类型别名:

template <typename T> using twin = pair<T, T>;twin<string> authors;   // authors是一个pair<string, string>

一个模板类型别名是一族类的别名。
当我们定义一个模板类型别名时,可以固定一个或多个模板参数。

类模板的static成员
与任何其他static数据成员相同,模板类的每个static数据成员必须有且仅有一个定义。但是,类模板的每个实例都有一个独有的static对象。

0 0
原创粉丝点击