c++ 模板与泛型编程

面向对象编程和泛型编程都能处理在编写程序时不知道类型的情况。其中,OOP 能处理类型在程序运行之前都未知的情况,泛型编程在编译时就能知道类型了。容器、迭代器、泛型算法都是泛型编程的例子。

一、定义模板

1、函数模板

模板定义以关键字 template 开始,后跟一个用 <> 包围,用逗号分隔的模板参数列表。模板参数表示在定义时用到的类型或值。使用模板时要指定模板实参。
template <typename T>
bool compare(const T &v1, const T &v2)
{
    return v1<v2 ? true : false;
}
调用函数模板时,编译器用函数实参来推断模板实参,然后实例化出一个特定版本的函数。
模板参数前必须使用关键字 class 或 typename,两个含义相同。建议使用typename。
 
函数模板可以声明为inline或者constexpr。
template <typename T> inline T min(const T&, const T&);

编写泛型代码有两个准则:

  1. 模板中的函数参数应该是const的引用。引用保证了函数可以用于不能拷贝的类型,如unique_ptr,IO类型等。
  2. 函数体中的条件判断仅使用 "<" 比较运算

模板编译:

编译器遇到模板定义时不生成代码,当实例化出模板的一个特定版本时才生成代码。这会影响错误何时被检测到。

定义类时,普通的成员函数一般放在源文件中。但是模板不同,模板的头文件通常既包括声明也包括定义。因为编译器需要知道函数模板或类模板成员函数的完整定义才能进行实例化。

所以,大多数编译错误在实例化期间才报告出来。

 

2、类模板

类模板不同于函数模板的地方在于,编译器不能为类模板推断参数类型

template <typename T> class Student {}
使用类模板时需要提供显式模板实参列表,编译器根据模板实参来实例化出特定的类。
Student<int> stu;   // 使用类模板
template <> class Student<int> {};  // 当向上一行那样使用类模板时,编译器实例化出的类就是这样的。

类模板的成员函数:

可以定义在类模板内部,也可以定义在外部。定义在类模板内部的函数隐式声明为内联函数。定义在类模板外部的成员的函数必须以关键字template开始,后接类模板参数列表。

template <typename T> int Student<T>::GetAge();

默认情况下,一个类模板的成员函数只有用到它时才进行实例化。

类模板和友元:

如果一个类模板包含一个非模板友元,则该友元可以访问该模板的所有实例。

如果友元也是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例。

1)一对一友好关系

template <typename T> class Blob{
    friend class BlobPtr<T>;  // 每个 Blob 实例将访问权限授予了同类型实例化的 BlobPtr。
    friend bool operator==<T> (const Blob<T>&,const Blob<T>&); // 将访问权限授予同类型实例化的 ==。
}

2)通用和特定的模板友好关系

template <typename T> class Blob{
    template <typename X> friend class Pal;  // Pal 的所有实例都是 Blob 的每个实例的友元。
}

3)令模板自己的类型参数成为友元

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

模板类型别名:

1)可以定义一个typedef来引用实例化的类,但不能引用模板

typedef Blob<string> StrBlob;//正确

2)可以使用using为类模板定义类型别名

template <typename T> using twins = pair<T, T>; // 为 pair<T, T> 定义了一个类型别名 twins
twins<string> authors;  // authors 是一个 pair<string,string>。

3)定义模板类型别名时,可以固定其中的部分模板参数

template <typename T> using twins = pair<T, unsigned>;  // 为 pair<T, unsigned> 定义了一个类型别名 twins
twins<string> authors;  // authors 是一个 pair<string, unsigned>。

如果类模板定义了static成员,那么模板的每个实例都有自己独有的static成员实例。

 

 
posted @   我就是欧部  阅读(142)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示