C++泛型编程学习(1)

泛型编程的核心是使用 模版, 模板分为函数模板和类模板


函数模板:

|| 函数模板:构建一种可以接受任意数据类型参数来执行内部逻辑的函数

语法:
template  --- 声明即将创建函数模板
<typename T>  // <class T>  --- typename或class
T ---- 指定的通用数据类型,通常情况都用T
template<typename T>  // template<class T>
void func (T  a) {
}

|| 函数模板的调用:1,自动进行类型推导,直接放进实参。2,手动类型声明

|| 调用时注意事项:(有关T --通用数据类型的指定)
// 使用函数模板时T必须被指明类型,且会被自动推导出一致的类型

1,调用函数模板进行自动类型推导时,因为缺少像普通函数一样的隐式类型转换
机制,T只能代表一个数据类型,即直接放入的参数数据类型必须一致
2,调用函数模板时,如函数不需要参数,那也必须指明T的数据类型
template<typename T>
void func(T a){
	test01()
}

//其调用方式!
>>func<int>()

|| 函数模板也可以发生重载

|| 重载时,普通函数与函数模板的调用规则

1,如果函数模板和普通函数都可以实现,优先调用普通函数
但如果普通函数中的参数匹配度不高(例如int形参却传入char实参,可以但匹配度不高)这时优先调用函数模板
但如果调用时使用了“空模板参数列表(即尖括号)”来强制调用函数模板,时优先调用函数模板
void myPrint(int a, int b)
{
	cout << "调用的普通函数" << endl;
}

template<typename T>
void myPrint(T a, T b) 
{ 
	cout << "调用的模板" << endl;
}

template<typename T>
void myPrint(T a, T b, T c) 
{ 
	cout << "调用重载的模板" << endl; 
}

|| 模板的局限性:在传入非内置数据类型(数组,自定义类等)时,函数逻辑一样正确但是无法正常执行。需要为特定类型提供具体化模板(即重载)

|| 具体化语法:

template<typename T>
bool myCompare(Person &p1, Person &p2){}

template<> bool myCompare(Person &p1, Person &p2){}

类模板:

|| 类模板语法(在声明模板template后面加类即类模板)

template<typename NameType, typename AgeName>
class ClassName{};

|| 类模板与函数模板在调用上的区别:

1,类模板使用只能用显示指定类型方式
2,类模板中的模板参数列表可以有默认参数

|| 类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成(编写时不会报错,因为在编译时其中的成员函数才创建)

|| 类模板对象做函数参数的传入方式 — 需要指明类模板对象中的T

一共有三种传入方式:第一种最常用!
   √ 1,直接传入指定类型后的对象 // func(Person<string, int> &p) √
	 2,传入类的参数模板化后的对象 // func(Person<T1, T2> &p)
	 3,传入整个类模板化后的对象 // func(T &p)
void printPerson1(Person<string, int> &p) 
{
	p.showPerson();
}
void test01()
{
	Person <string, int >p("孙悟空", 100);
	printPerson1(p);
}

//2、参数模板化
template <class T1, class T2>
void printPerson2(Person<T1, T2>&p)
{
	p.showPerson();
	cout << "T1的类型为: " << typeid(T1).name() << endl;
	cout << "T2的类型为: " << typeid(T2).name() << endl;
}
void test02()
{
	Person <string, int >p("猪八戒", 90);
	printPerson2(p);
}

//3、整个类模板化
template<class T>
void printPerson3(T & p)
{
	cout << "T的类型为: " << typeid(T).name() << endl;
	p.showPerson();

}
void test03()
{
	Person <string, int >p("唐僧", 30);
	printPerson3(p);
}

|| 题外话:当你需要调用的函数需要某些参数传入(作为形参或指明类型等等),但是该函数并没有接受这些参数的接口时。可以创建一个函数(拥有这些接口),再内部调用目标函数

|| 当类模板碰到继承时,需要指定出父类中T:

1,当父类是模板子类不是模板时,子类在声明的时候,要指定出父类中T的
  类型如果不指定,编译器无法给子类分配内存
2,当父类是模板子类也是模板,可以灵活指定出父类中T的类型
template<class T>
class Base{public: T a;}

//法一
class Son1 :public Base<int>

//法二,灵活
template<class T1, class T2>
class Son2 :public Base<T2>

||

发布了25 篇原创文章 · 获赞 40 · 访问量 4239

猜你喜欢

转载自blog.csdn.net/a13352912632/article/details/104235817
今日推荐