栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 模板与泛型编程

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 模板与泛型编程

模板与泛型编程

为了能更方便的使用STL模板库,先行了解模板与泛型编程的语法和思想

​ 模板就是泛型编程,为了编写更加通用的程序代码,实现算法与类分离————>代码复用

也即编写更加抽象的类和函数。

函数模板
template
返回值类型 函数名(参数列表){
    函数体;
}
//template是模板关键字<模板类型参数>
//typename可以用class替换;
//模板类型参数可以有很多,不是具体的类型
//每一个模板参数都需要用", "隔开
函数模板实例化—>模板函数
  • 实例化后变为模板函数:函数模板需要用具体的类型实例化
    • 使用:函数模板名<类型参数列表> (实参列表)
自动类型推导
  • 某些支持自动类型推导

    • 使用时传递了实参,根据实参类型进行推导,

      但有些情况可能产生二义性,此时需要提供<类型参数>

  • 某些不支持

    template
    void func(){//模板没有参数列表
    	cout << typeid(T).name() << endl;
    	cout << CAP << endl;
    }
    
    
    int main(int argc,char *argv[]){
    	func();//没有实例化类型
        return 0;
    }
    
    • 模板没有参数列表
    • 多种类型
    • 没有实例化类型
函数模板特化

针对某些特殊的类型(C风格的字符串),通用的模板可能不适用

需要针对该类型写一个特化的函数(但此前须有通用版本才能称为特化)

template<> 返回值类型 函数名(参数列表){
    函数体;
}
函数模板支持非类型参数
//c++11
template
int compare(const char (&p1)[N],const char (&p2)[M]){
	cout << N << "," << M << endl;
	return strcmp(p1,p2);
}

int main(int argc,char *argv[]){
	int ret = compare("Hello","hi");
	cout << ret << endl;
	int a = 6,b = 3;
	compare<6,3>("Hello","hi");
	//compare("Hello","hi");
	const int x = 6, y = 3;
	compare("Hello","hi");
	char s1[] = "Hello";
	char s2[] = "hi";
	const int m = strlen(s1)+1,n = strlen(s2)+1;
	//compare("Hello","hi");
    return 0;
}

在对非类型模板参数实例化时,只能用常量或者常量表达式

模板编译

当编译器遇到一个模板定义时, 它并不生成代码,只有当实例化出模板的一个特定版本时, 编译器才会生成代码,所以模板会二次编译,一次编译检查模板本身的语法, 第二次是模板实例化后,生成特定的版本和类进行编译

在多文件编程中,函数和类的声名放在头文件中,函数和类的实现放在文件中.cpp

但是模板的声名和定义是不能放在不同的文件中,因为如果只包含声名,在实例化时,将无法得到模板的定义,所以模板编程中会把模板的声名和定义直接放在头文件中

编译错误报告
  1. 编译模板代码,针对模板本身进行语法检查,需要代码满足模板规则

  2. 使用模板实例时,检查实例化时模板参数的个数是否相等 ,类型是否匹配

  3. 模板实例化,根据模板用具体的实例化,生成具体的模板函数或者模板类

    • 再次编译模板函数和模板类,进行语法检查,之哦于在这个阶段才能发现类类型的问题(如:不支持的类型,没有连接到函数)
普通函数和模板函数同名

如果普通函数和模板函数除了函数体外完全一致时, 会优先调用普通函数,如果像调用函数模板,则需要显示类型实例化,函数模板中针对类型特化的版本,则调用特化的版本。

template
void func(T a){}
tmeplate<>
void func(int a){}
void func(int a){}

func(10);//普通
func(10);//特化
func('a');//通用
尾置返回类型
template
auto maxarr(T beg, T end)->decltype(*beg){
    
}
类模板
#include 
#include 
using namespace std;
//通用的类模板
template
class Compare{
public:
	Compare(const T& a,const T& b):a(a),b(b){
		cout << "通用版本" << endl;	
	}

	T max(void){
		return a
		return a
		return a;
	}
	T getSecond(){
		return b;
	}
private:
	T a;
	T b;
};
//成员特化
template<> char* Compare::max(){
	cout << "成员特化" << endl;
	return strcmp(a,b)<0?b:a;
}

template<> char *Compare::min(){
	cout << "成员特化" << endl;
	return strcmp(a,b)<0?a:b;
}


//全员特化版本
template<>
class Compare{
public:
	Compare(const char * const & a,const char * const & b):a(a),b(b){
		cout << "特化" << endl;	
	}
	const char *max(void){
		return strcmp(a,b)<0?b:a;
	}
	const char *min(void){
		return strcmp(a,b)<0?a:b;
	}
	const char *getFirst(){
		return a;
	}
	const char *getSecond(){
		return b;
	}
private:
	const char *a;
	const char *b;
};

int main(int argc,char *argv[]){
	Compare c(1,3);//无法进行隐式类型推导
	cout << c.max() << endl;
	cout << c.min() << endl;
	Compare c1("Hello","hello");
	cout << c1.max() << endl;
	cout << c1.min() << endl;
	char s1[10] = "hello";
	char s2[10] = "Hello";
	Compare c2(s1,s2);
	cout << c2.max() << endl;
	cout << c2.min() << endl;
    return 0;
}

  • 类模板无法进行自动类型推导
针对特殊类型进行全员特化
  • 类所有的属性和方法重写

    template<>
    class 类模板名<特化的类型>{
        
    }
    
针对特殊类型进行成员特化
  • 只针对几个函数特化

    template<>返回值类型 类模板名<特化的类型>::成员方法名(参数列表){
        
    }
    
针对特殊类型进行偏特化
#include 
using namespace std;

template
class C{
public:
	C(){
		cout << "T" << endl;
	}
};
//针对数组的偏特化
template
class C{
public:
	C(){
		cout << "T[]" << endl;
	}
};
//针对指针的偏特化
template
class C{
public:
	C(){
		cout << "T*" << endl;
	}
};

template
class A{
public:
	A(){
		cout << "T1,T2,T3" << endl;
	}				
};

template
class A{
public:
	A(){
		cout << "T1,T2,T2" << endl;
	}
};

template
class A{
public:
	A(){
		cout << "T1,T1,T1" << endl;
	}
};

template
class A{
public:
	A(){
		cout << "T1,T2[],T2[]" << endl;
	}
};

template
class A{//针对指针的偏特化
public:
	A(){
		cout << "T1*,T1*,T1*" << endl;
	}	
};

template
class A{//针对三个类型相同情况下的偏特化
public:
	A(){
		cout << "T1[],T1[],T1[]" << endl;
	}	
};


int main(int argc,char *argv[]){
	C c1;
	C c2;
	C c3;
	A a1;
	A a2;
	A a3;
	A a4;
	A a5;
	A a6;
    return 0;
}

  • 针对指针或者数组类型的偏特化,或者针对类型本身特殊情况的特化
  • 在实例化时会选择特化程度更高的实例化
类模板允许非类型参数

非类型参数在实例化时必须是常量或者常量表达式

类模板允许缺省值

缺省模板参数需要满足靠右原则

函数模板在C++11以后也允许有模板缺省参数

普通类中含有模板成员方法 可变长类型模板参数
void func(){
    
}

template
void func(const T& t,const Args& ...args){
    //cout << t << " " << endl;
    func(args...);//func()
}

template
class X{
    template
    void emplace(iterator pos,Args&& ...args){
        
    }
};
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1037919.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号