C++学习日记
·
1.2.4普通函数与函数模板的区别
普通函数与函数模板区别:
- 普通函数调用时可以发生自动类型转换(隐式类型转换)
- 函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
- 如果利用显示指炭类型的方式,可以发生隐式类型转换
示例:
#include<iostream> using namespace std; //普通函数与函数模板区别 //1.普通函数调用可以发生隐式类型转换 //2.函数模板 用自动类型推导,不可以发生隐式类型转换 //3.函数模板 用显式指定类型,可以发生隐式类型转换 //普通函数 int myAdd01(int a, int b) { return a + b; } //函数模板 template<class T> T myAdd02(T a,T b) { return a + b; } void test01() { int a =10; int b = 20; char c ='c'; // a- 97 c -99 cout<<myAdd01(a,c)<< endl; //自动类型推导不会发生隐式类型转换 //cout<<myAdd02(a,c)<<endl; //显示指定类型会发生隐式类型转换 cout<<myAdd02<int>(a,c)<<endl; } int main() { test01(); system("pause"); return 0; }总结:建议使用显示指定类型的方式,调用函数模板,因为可以自己确定通用类型T
1.2.5普通函数与函数模板的调用规则
调用规则如下:
1.如果函数模板和普通函数都可以实现,优先调用普通函数
2.可以通过空模板参数列表来强制调用函数模板
3.函数模板也可以发生重载
4.如果函数模板可以产生更好的匹配,优先调用函数模板
示例:#include<iostream> using namespace std; //普通函数与函数模板调用规则 //1、如果函数模板和普通函数都可以调用,优先调用普通函数 //2、可以通过空模板参数列表强制调用函数模板 //3、函数模板可以发生函数重载 //4、如果函数模板可以产生更好的匹配,优先调用函数模板 void myPrint (int a, int b); { cout<<"调用的普通函数"<<endl; } template<class T> evoid myPrint(T a,T b) { cout<<"调用的模板"<< endl; } template<class T> evoid myPrint(T a,T b,T c) { cout<<"调用的重载的模板"<< endl; } void testo1() { int a =10; int b = 20; //myPrint(a,b); //通过空模板参数列表,强制调用函数模板 //myPrint<>(a,b); //myPrint (a, b, 100); //如果函数模板产生更好的匹配,优先调用函数模板 char c1 ='a'; char c2 ='b'; myPrint(c1, c2); } int main() { test01(); system("pause"); return 0; }总结:既然提供了函数模板,最好就不要提供普通函数,否则容易出现二义性
1.2.6模板的局限性
局限性:
- 模板的通用性并不是万能的
例如:
template<class T> void f(T a, T b) { а=b; }在上述代码中提供的赋值操作,如果传入的a和b是一个数组,就无法实现了。
再例如:template<class T> void f(T a, T b) { if(a > b) { ....} }在上述代码中,如果T的数据类型传入的是像Person这样的自定义数据类型,也无法正常运行
因此C++为了解决这种问题,提供模板的重载,可以为这些特定的类型提供具体化的模板
示例:#include<iostream> using namespace std; #include <string> //模板局限性 //模板并不是万能的,有些特定数据类型,需要用具体化方式做特殊实现 class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } //姓名 string m_Name; //年龄 int m_Age; } //对比两个数据是否相等函数 template<class T> bool myCompare(T &a, T &b) { if (a == b) { return true; } else { return false; } } //利用具体化Person的版本实现代码,具体化优先调用 template<> bool myCompare(Person &p1,Person &p2) { if(pl.m_Name == p2.m_Name && pl.m_Age == p2.m_Age) { return true; } else { return false; } void test01() { int a =10; int b = 20; bool ret = myCompare(a, b); if(ret) { cout << "a == b" << endl; } else { cout << "a != b" << endl; } } void test02() { Person p1("Tom",10); Person p2("Tom",10); bool ret = myCompare(pl, p2); if (ret) { cout<<"pl == p2" << endl; } else { cout << "pl != p2" << endl; } } int main() { test01(); test02(); system("pause"); return 0; }总结:
- 利用具体化的模板,可以解决自定义类型的通用化
- 学习模板并不是为了写模板,而是在STL能够运用系统提供的模板
1.3 类模板
1.3.1 类模板语法
类模板作用:
- 建立一个通用类,类中的成员数据类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template<typename T>
类
解释:
template ---- 声明创建模板
typename ---- 表面其后面的符号是一种数据类型,可以用class代替
T ------ 通用的数据类型,名称可以替换,通常为大写字母
示例:#include<iostream> using namespace std; #include<string> //类模板 template<class NameType, class AgeType> class Person { public: Person (NameType name,AgeType age) { this->m_Name = name; this->m_Age = age; } void showPerson() { cout<<"name:"<<this->m_Name <<"age:"<<this->m_Age << endl; } NameType m_Name; AgeType m_Age; }; void test01() { Person<string,int> pl("孙悟空",999); pl.showPerson(); } int main() { test01(); system("pause"); return 0; }总结:类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板。
1.3.2类模板与函数模板区别
类模板与函数模板区别主要有两点:
1.类模板没有自动类型推导的使用方式
2.类模板在模板参数列表中可以有默认参数
示例:#include<iostream> using namespace std; #include<string> //类模板与函数模板区别 template<class NameType, class AgeType = int> class Person { public: Person (NameType name,AgeType age) { this->m_Name = name; this->m_Age = age; } void showPerson() { cout<<"name:"<<this->m_Name <<"age:"<<this->m_Age << endl; } NameType m_Name; AgeType m_Age; }; //1、类模板没有自动类型推导使用方式 void test01() { //Personp(孙悟空”,1000);错误,无法用自动类型推导 Person<string,int> p("孙悟空",1000);//正确,只能用显示指定类型 p.showPerson(); } //2、类模板在模板参数列表中可以有默认参数 void test02 { Person<string> p("猪八戒",999); p.showPerson(); } int main() { test01(); test02(); system("pause"); return 0; }总结:
- 类模板使用只能用显示指定类型方式
- 类模板中的模板参数列表可以有默认参数
1.3.3类模板中成员函数创建时机
类模板中成员函数和普通类中成员函数创建时机是有区别的:
- 普通类中的成员函数一开始就可以创建
- 类模板中的成员函数在调用时才创建
示例:
class Person1 { public: void showPerson1() { cout<"Person1 show"<endl; } }; class Person2 { public: void showPerson2() { cout << "Person2 show" << endl; } }; template<class T> class MyClass { public: T obj; //类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成 void func1() { obj.showPerson1(); } void func2() { obj.showPerson2(); } }; void teste1() { MyClass<Person1> m; m.fun1(); //m.fun2();//编译会出错,说明函数调用才会去创建成员函数 } int main() { test01(); system("pause"); return 0; }总结:类模板中的成员函数并不是一开始就创建的,在调用时才去创建。
更多推荐



所有评论(0)