🤖 AI文章摘要 gemini-2.0-flash-lite

这篇文章介绍了C++中的泛型编程,主要通过函数模板和类模板实现。函数模板允许编写与类型无关的函数,通过模板实例化生成具体的函数。类模板则用于创建与类型无关的类,同样需要实例化才能生成具体的类。文章还详细阐述了函数模板和类模板的实例化方式(显式和隐式),以及它们与重载、类中成员的实现、友元函数、作为函数参数和继承等方面的关系和注意事项。

泛型概述

C++泛型

使用抽象数据类型定义的通用函数或通用类就是模板. 模板编程思想就是泛型编程.

  • 编译器只对模板进行语法检查, 并不编译成指令. 模板实例化后才会生成指令.
  • 模板实例化: 确定抽象类型并产生相应具体的模板函数或模板类的过程. 实例化后编译器会对模板实例进行检查并生成指令

函数模板


//函数模板
template <class/typename absType, ...>  注: 定义时class和typename功能完全相同, typename还有另外的用途
_RetType funcName(arg1,..){
	//function define
}
  • 函数模板实例化
    • 直接实例化: template<> 返回值类型 函数名<参数类型列表>(参数列表){函数定义} 调用方式和普通函数一致.
      • 注意: 显式实例化法的模板函数优先级是高于隐式具体法的模板函数的!!!!!!!!!!!
    • 参数类型列表: function<absType,...>(arg1,...); 调用时通过参数类型列表实例化特定的函数模板.
    • 自动类型推导: function(arg1,...); 调用时根据函数参数列表推导抽象数据类型, 实例化特定函数模板.
  • 模板函数与重载: 模板函数与普通函数间可以发生函数重载. 发生重载时优先调用普通函数. 可以使用参数类型列表(可空), 强制调用模板函数 (3)函数模板的局限性: 函数模板并不是万能的, 若抽象数据类型是自定义数据类型, 函数包含一些特殊操作, 编译器是不知道如何执行的. 一个办法就是类中对特定操作符进行重载, 另一个办法就是使用显式具体化方法重写一个模板函数.

类模板


template <class T1, class T2>
class Class_template
{
	class memberClass;                       //类模板中的成员类
	(static) void classFunction();          //类模板的成员函数
	T1   variable;                                  //非静态成员变量
	static T2 static_variable;                 //静态成员变量
};
//1. 类模板的成员类类外实现:(类模板的成员类也是类模板)
template<class T1, class T2 >
class Class_template<T1, T2>::memberClass {类模板的类模板定义}

//2. 类模板的成员函数的类外实现: (类模板的成员函数也是函数模板)
template <class T1 , class T2>
void Class_template<T1, T2>::classFunction(){ 类模板的函数模板定义 } 

//3. 类模板静态变量的类外初始化: 
template <class T1 , class T2>
T1 person<T1, T2>::staticMember = xxx;

//4. 类模板的友元函数: 首先要明白, 类模板的友元函数应该是一个全局函数并且需要访问类模板的成员变量, 所以它应该是一个全局函数模板
// 类内声明并实现友元函数, 这个友元函数直接上升为全局函数
template<class T1, class T2>
class Class_template{
	friend void Function_template(){
	//function define
	}
}
// 类内声明类外实现友元函数, 有一定的难度. 
/*声明相应类模板*/
template<class T1, class T2>
class Class_template;

/*声明友元函数模板*/
template<class T1, class T2>
void Function_template(Class_template<T1, T2> p); 

/*friend声明自动上升为全局函数, 为了确保声明的是函数模板需要加尖括号*/
template<class T1, class T2>
class Class_template{
	friend Function_template<>(Class_template);
}

/*实现友元函数*/
template <class T1,class T2> 
void Function_template(){
	//function define
}
  • 类模板的实例化:

    • 直接实例化: template<> class 类名<参数类型列表> {类定义}
      • 注意: 显式实例化法的模板类优先级是高于隐式实例化法模板类的!!!!!!!!!
    • 创建时实例化: 通过参数类型列表去实例化并调用. 考虑到兼容性问题, 类模板函数需要单独实例化(实例化方式同函数模板)
    • 类模板函数也可以直接实例化, 实例化时给出的类模板示例参数同时完成类模板的实例化
  • 类模板作为函数参数

    
    //普通函数里的类模板要直接提供实例化
    void test( Class_template<string, string> &c ){ 函数定义 }
    int main(void){
    	Class _template<string, string> c;
    	test(p);// 这是直接传入写死的类型
    }
    //函数模板中的类模板的抽象类型可以通过函数模板的自动类型推导确定
    template<class T1, class T2>
    void test( Class_template<T1, T2> &c ){ 函数模板定义 }
    int main(void){
    	Class_template<string, string> c;
    	test<string, string>( c );
    };
    或: 
    template <class T1>
    void test( T1 &c ){ 函数模板定义 }
    int main(void){
    	Class_template<string, string> c;
    	test(c);
    }
    

  • 类模板的继承

    
    //类模板间可以继承, 但基类模板的抽象类型, 派生类要负责确定. 
    template <class T1 , class T2, class T3>
    class Class_tempalte2 : public Class_template<T1, T2> { 类模板定义 } 
    //普通类继承类模板需要对类模板进行实例化. 
    class CommentClass : public Class_template<int , double> { 类定义 }