无锡网站seo外包,大良营销网站建设咨询,做阿里巴巴英文网站,中企动力是做哪方面销售一.模板模板概念 模板就是建立通用的模具#xff0c;大大提高复用性 模板的特点#xff1a; 1.模板不可以直接使用#xff0c;它只是一个框架 2.模板的通用并不是万能的 C另一种编程思想称为泛型编程#xff0c;主要利用的技术就是模板。 C提供两种模板机制:函数模板和类模…
一.模板模板概念 模板就是建立通用的模具大大提高复用性 模板的特点 1.模板不可以直接使用它只是一个框架 2.模板的通用并不是万能的 ·C另一种编程思想称为泛型编程主要利用的技术就是模板。 ·C提供两种模板机制:函数模板和类模板 二.函数模板 函数模板作用: 建立一个通用函数其函数返回值类型和形参类型可以不具体制定用一个虚拟的类型来代表。 2.1语法
templatetypename T
函数声明或定义
自动推导类型代码实例
#include iostream
using namespace std;
templatetypename T
void my_swap(T a, T b) {T temp a;a b;b temp;
}int main() {int a 10,b 20;char a2 a, b2 b;string a3 abc, b3 efg;my_swap(a, b);my_swap(a2, b2);my_swap(a3, b3);cout a a b b endl;cout a2 a2 b2 b2 endl;cout a3 a3 b3 b3 endl;return 0;
} 显示指定类型代码
#include iostream
using namespace std;
templatetypename T
void my_swap(T a, T b) {T temp a;a b;b temp;
}int main() {int a 10,b 20;char a2 a, b2 b;string a3 abc, b3 efg;my_swapint(a, b);my_swapchar(a2, b2);my_swapstring(a3, b3);cout a a b b endl;cout a2 a2 b2 b2 endl;cout a3 a3 b3 b3 endl;return 0;
} 2.2注意事项 注意事项: 1.自动类型推导必须推导出一致的数据类型T,才可以使用 2.模板必须要确定出T的数据类型才可以使用 代码实例
#include iostream
using namespace std;
templatetypename T
void my_swap(T a, T B) {T temp a;a b;b a;
}templatetypename T
void fun() {cout 函数模板调用 endl;
}int mian() {//fun();//报错因为不能推理出T的类型int a 10, b 20;funint(); //必须这样写int换为其它类型也可//my_swap(10, p);//报错类型不一致my_swap(20, 90); my_swapint(20, 90); my_swap(a, b);return 0;
}
2.3普通函数和模板函数的区别 普通函数与函数模板区别: ·普通函数调用时可以发生自动类型转换(隐式类型转换) ·函数模板调用时如果利用自动类型推导不会发生隐式类型转换 ·如果利用显示指定类型的方式可以发生隐式类型转换 #include iostream
using namespace std;
void fun(int one, int two) {cout one one two two endl;
}
templatetypename T
void fun1(T one, T two) {cout one one two two endl;
}void ce() {int a 10, b 20;char c a;fun(a, b);fun(a, c);fun1(a, b);//fun1(a, c); //报错因为自动推理类型不会发生隐式转换fun1int(a, c);}
int main() {ce();return 0;
} 总结:建议使用显示指定类型的方式调用函数模板因为可以自己确定通用类型T 2.4普通函数和函数模板的调用规则 调用规则如下: 1.如果函数模板和普通函数都可以实现优先调用普通函数 2.可以通过空模板参数列表来强制调用函数模板 3.函数模板也可以发生重载 4.如果函数模板可以产生更好的匹配,优先调用函数模板 代码实例
#include iostream
using namespace std;
void fun(int a,int b) {cout a b endl;cout 普通函数调用 endl;
}templateclass T
void fun(T a, T b) {cout a b endl;cout 模板函数调用 endl;
}templateclass T
void fun(T a, T b,T c) {cout a b c endl;cout 模板函数调用 endl;
}
int main() {fun(10,20); //默认调用普通函数fun(10,90); //空列表强制调用模板函数fun(10,90,90); //模板函数可以发生重载return 0;
}2.5模板的局限性 局限性 模板的通用性并不是万能的 代码实例
#include iostream
using namespace std;class person {
public:person(string name, int temp) {this-name name;this-temp temp;}int temp;string name;
};template class T
bool eq(T a, T b) {if (a b) {return true;}else {return false;}
}int main() {person p1(tom, 20);person p2(tom, 20);//报错因为自定义的类型重载‘’运算符if (eq(p1, p2)) {cout endl;}else {cout ! endl;}return 0;
} 此时模板函数不报错但运行时会报错。因为类的‘’没有重载。 代码实例
#include iostream
using namespace std;
class person {
public:person(string name, int temp) {this-name name;this-temp temp;}int temp;string name;
};
template class T
bool eq(T a, T b) {if (a b) {return true;}else {return false;}
}//实例化模板函数
template bool eq(person a, person b) {if (a.name b.name a.temp b.temp) {return true;}else {return false;}
}int main() {person p1(tom, 20);person p2(tom, 20);//报错因为自定义的类型重载‘’运算符if (eq(p1, p2)) {cout endl;}else {cout ! endl;}return 0;
} 此时可以运行函数模板实例化相当于模板的补充。 三.类模板 类模板作用: ·建立一个通用类类中的成员数据类型可以不具体制定用一个虚拟的类型来代表。 类模板不能使用自动推导类型只能用显示指定的方法。 3.1语法
templatetypename T1, typename T2
class person {
public:person(T1 name, T2 age) {this-name name;this-age age;}T1 name;T2 age;
}; 代码实例
#include iostream
using namespace std;
templatetypename T1, typename T2
class person {
public:person(T1 name, T2 age) {this-name name;this-age age;}T1 name;T2 age;
};int main() {personstring, int P(TOM, 90);cout P.name P.age endl;return 0;
} 3.2类模板和函数模板区别 类模板与函数模板区别主要有两点: 1.类模板没有自动类型推导的使用方式 2.类模板在模板参数列表中可以有默认参数 代码实例
#include iostream
using namespace std;
//类模板可以添加默认参数但是要优先右边全有默认参数yuanze
templateclass T1string, typename T2int
class person {
public:person(T1 name, T2 age) {this-name name;this-age age;}T1 name;T2 age;
};
int main() {//person P(TOM, 90); //报错因为。类模板没有自动推导型personstring, int P(TOM, 90);//有默认参数可以省略类型但是不能省略person P1(SOM, 900);cout P.name P.age endl;cout P1.name P.age endl;return 0;
} 注意 不可以省略设置默认参数时优先右边。 3.3类模板中成员函数创建时机 类模板中成员函数和普通类中成员函数创建时机是有区别的: 1.普通类中的成员函数—开始就可以创建 2.类模板中的成员函数在调用时才创建 代码实例
#include iostream
using namespace std;
class person1 {
public:void fun1() {cout person1的fun函数调用 endl;}
};
class person2 {
public:void fun2() {cout person2的fun函数调用 endl;}
};templatetypename T
class p {
public:p(T p) {this-fun p;}T fun;void fun1() {//定义时不报错只有实例化后调用此函数才会检测是否报错。fun.fun1();}void fun2() {//定义时不报错只有实例化后调用此函数才会检测是否报错。fun.fun2();}
};int main() {person1 p1;pperson1 p(p1);//此时会正常运行不会报错因为没有调用p.fun2();p.fun1();//p.fun2(); 运行报错return 0;
}
3.4类模板做函数参数 —共有三种传入方式: 1.指定传入的类型------------直接显示对象的数据类型 ⒉参数模板化------------------将对象中的参数变为模板进行传递 3.整个类模板化----------------将这个对象类型模板化进行传递 3.4.1指定传入
代码实例
#include iostream
using namespace std;
//默认参数
templateclass T1string,class T2int
class person {
public:T1 name;T2 id;person(T1 name, T2 id) {this-name name;this-id id;}void fun() {cout name id endl;}
};//此函数不是模板函数所以其参数要具体的参数
void fun(personstring, int p) {p.fun();
}int main() {personstring, int p(孙悟空, 78);fun(p);return 0;
} 3.4.2参数模板化
代码实例
#include iostream
using namespace std;
//默认参数
templateclass T1 string, class T2 int
class person {
public:T1 name;T2 id;person(T1 name, T2 id) {this-name name;this-id id;}void fun() {cout name id endl;}
};//实际上是创建模板函数
templateclass T1,class T2
void fun(personT1, T2 p) {p.fun();
}int main() {personstring, int p(猪八戒, 19);fun(p);return 0;
}
3.4.3类模板化
代码实例
#include iostream
#include string
using namespace std;
//默认参数
templateclass T1 string, class T2 int
class person {
public:T1 name;T2 id;person(T1 name, T2 id) {this-name name;this-id id;}void fun() {cout name id endl;}
};//将整个类作为一个类型创建模板函数
templateclass T1
void fun(T1 p) {p.fun();
}int main() {personstring, int p(沙僧, 19);fun(p);return 0;
} 总结: 通过类模板创建的对象,可以有三种方式向函数中进行传参 使用比较广泛是第一种:指定传入的类型 3.5类模板与继承 当类模板碰到继承时,需要注意一下几点: 1.当子类继承的父类是一个类模板时子类在声明的时候要指定出父类中T的类型如果不指定编译器无法给子类分配内存。 2.如果想灵活指定出父类中T的类型,子类也需变为类模板。 1.代码实例
#include iostream
using namespace std;
templatetypename T
class father {
public:T name;
};//class father :public son
//如果想灵活指定出父类中T的类型,子类也需变为类模板。
class son :public fatherstring {
public:son(string name) {this-name name;}void fun() {cout this-name endl;}
};int main() {son s(Tom);s.fun();return 0;
} 2.代码实例
#include iostream
using namespace std;
templatetypename T
class father {
public:T name;
};//class father :public son
//父类是模板类时子类继承时要指定模板列表
templateclass T1,class T2
class son :public fatherT2 {
public:T1 id;son(T1 id,T2 name) {this-name name;this-id id;}void fun() {cout this-name endl;cout this-id endl;}
};int main() {sonint,string s(100,Tom);s.fun();return 0;
} 3.6类模板成员函数类外实现
代码实例
#include iostream
using namespace std;
templateclass T1,class T2
class person {
public:T1 name;T2 id;person(T1 name, T2 id);void fun();};templateclass T1, class T2
personT1,T2::person(T1 name, T2 id) {this-name name;this-id id;
}templateclass T1, class T2
void personT1, T2::fun() {cout name endl;cout id endl;
}int main() {personstring, int p(tom, 100);p.fun();return 0;
} 总结:类模板中成员函数类外实现时需要加上模板参数列表 3.7类模板分文件编写
问题: ·类模板中成员函数创建时机是在调用阶段导致分文件编写时链接不到 解决 ·解决方式1:直接包含.cpp源文件 ·解决方式2∶将声明和实现写到同一个文件中并更改后缀名为.hpphpp是约定的名称并不是强制 代码
person.hpp
#include iostream
using namespace std;templateclass T1 string, class T2 int
class person {
public:T1 name;T2 age;person(T1 name, T2 age);void person_show();
};templateclass T1, class T2
personT1, T2::person(T1 name, T2 age) {this-name name;this-age age;
}templateclass T1, class T2
void personT1, T2::person_show() {cout this-name endl this-age endl;
}person.cpp
#include person.hpp;
int main() {person p(猪八戒, 100);p.person_show();return 0;
}
3.8类模板和友元 全局函数类内实现-直接在类内声明友元即可 全局函数类外实现·需要提前让编译器知道全局函数的存在 类内实现 代码
#include iostream
using namespace std;
templateclass T1string,class T2int
class person {
//定义友元函数属于全局函数friend void person_show(personT1,T2 p) {cout p.name endl p.age endl;}
public:person(T1 name, T2 age);
private:T1 name;T2 age;
};templateclass T1, class T2
personT1,T2::person(T1 name, T2 age) {this-name name;this-age age;
}int main() {person p(小明, 100);person_show(p);return 0;
} 类外实现
代码
#include iostream
using namespace std;//先声明有person类防止报错
templateclass T1, class T2
class person;//写在person定义之前防止找不到报错
templateclass T1, class T2
void person_show(personT1, T2 p) {cout p.name endl p.age endl;
}templateclass T1,class T2
class person {//friend void person_show(personT1, T2 p); //错误写法,因为person_show是模板函数此时T1是模板没的T1friend void person_show(personT1, T2 p);//正确写法加入模板列表声明是模板
public:person(T1 name, T2 age);
private:T1 name;T2 age;
};templateclass T1, class T2
personT1,T2::person(T1 name, T2 age) {this-name name;this-age age;
}int main() {personstring, int p(猪八戒, 100);person_show(p);return 0;
} 总结:建议全局函数做类内实现用法简单而且编译器可以直接识别 类模板案例 案例描述: 实现一个通用的数组类要求如下 。可以对内置数据类型以及自定义数据类型的数据进行存储 。将数组中的数据存储到堆区 。构造函数中可以传入数组的容量 。提供对应的拷贝构造函数以及operator防止浅拷贝问题。 。提供尾插法和尾删法对数组中的数据进行增加和删除。 。可以通过下标的方式访问数组中的元素。 。可以获取数组中当前元素个数和数组的容量 代码
myArray.hpp
#pragma
#include iostream
using namespace std;templateclass T
class myArray {
public:myArray(int capacity);myArray(myArray p);~myArray();//重载防止浅拷贝myArray operator(const myArray p) {if (this-Array ! NULL) {delete[] this-Array;this-Array NULL;}this-capacity p.capacity;this-size p.size;this-Array p.Array;for (int i 0; i this-size; i) {this-Array[i] p.Array[i];}}T operator[](int index) {return this-Array[index];}void push_back(const T val);void pop_back();int getsize() {return this-size;}int getcapacity() {return this-capacity;}
private:T* Array;int size;int capacity;
};//拷贝构造函数注意要用深拷贝
templateclass T
myArrayT::myArray(myArray p) {this-size p.size;this-capacity p.capacity;this-Array new T[this-capacity];for (int i 0; i this-size; i) {this-Array[i] p.Array[i];}
}//有参构造函数
templateclass T
myArrayT::myArray(int capacity) {this-capacity capacity;this-Array new T[this-capacity];this-size 0;
}//析构函数
templateclass T
myArrayT::~myArray() {if (this-Array ! NULL) {delete[] this-Array;this-Array NULL;}
}templateclass T
void myArrayT :: push_back(const T val) {if (this-size this-capacity) {return;}this-Array[this-size] val;
}templateclass T
void myArrayT ::pop_back() {if (this-size 0) {return;}--this-size;
}
main.cpp
#include myArray.hpp
class person {
public:string name;int age;person() {}person(string name, int age) {this-name name;this-age age;}
};void myprintf(myArrayperson p) {for (int i 0; i p.getsize(); i) {cout p[i].name p[i].age endl;}
}void fun() {person p1(小明, 100);person p2(小壮, 130);person p3(小聪, 103);person p4(小红, 1560);person p5(小懒, 190);//调用默认构造函数myArrayperson p(10);p.push_back(p1);p.push_back(p2);p.push_back(p3);p.push_back(p4);p.push_back(p5);cout p.getsize() endl;cout p.getcapacity() endl;myprintf(p);p.pop_back();cout 弹出最后一个 endl;myprintf(p);cout 判断拷贝构造函数 endl;myArrayperson p6(p);myprintf(p6);cout 判断operator endl;myArrayperson p7(0);p7 p;myprintf(p7);
}
int main() {fun();return 0;
}