C++之泛型编程-创新互联
目录
创新互联秉承实现全网价值营销的理念,以专业定制企业官网,成都网站建设、做网站,小程序开发,网页设计制作,移动网站建设,营销型网站建设帮助传统企业实现“互联网+”转型升级专业定制企业官网,公司注重人才、技术和管理,汇聚了一批优秀的互联网技术人才,对客户都以感恩的心态奉献自己的专业和所长。模板
模板的特点
函数模板
前言
函数模板的使用方式
函数模板具体案例
使用模板的注意事项
普通函数与函数模板间的区别
具体案例
普通函数与函数模板调用规则
模板的局限性
具体化模板
类模板
前言
类模板与函数模板的区别
类模板中成员函数创建时机
类模板对象做函数的参数
传入方式
具体案例
类模板与继承
前言
子类指定具体类型案例
子类不指定具体类型案例
类模板成员函数的类外实现
类模板分文件编写
1.直接包含源文件
2.将.h和.cpp文件中的内容写到一起,后将后缀名改为.hpp文件
类模板与友元
模板前言:
- C++中相对于面向对象的另一种编程思想就是泛型编程,主要利用的技术就是模板
- C++提供了两种模板机制(函数模板和类模板)
概念:模板就是建立通用的模具,大大提高复用性
模板的特点- 模板不可以直接使用,它只是一个框架
- 模板通用性很强,但是并不是万能的
使用模板的目的:提高复用性,将类型参数化
函数模板 前言作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表
语法:
//声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用的数据类型
template函数声明或函数定义
解释:
- template:声明创建模板
- typename:表明其后面的符号为一种数据类型(该关键字也可以用class代替)
- T:通用的数据类型;名称可以替换,通常为大写字母。
- 自动类型推导:向交换模板函数中传递的参数的类型会被自动解析
- 显示指定类型:指定模板的具体数据类型
#define _CRT_SECURE_NO_WARNINGS 1
#includeusing namespace std;
//函数模板
template//通用交换函数模板
void mySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
void main() {
int a = 10;
int b = 20.0;
//自动类型推导(a和b的数据类型会被自动解析)
mySwap(a, b);
cout<< "a:"<< a<< "\tb:"<< b<< endl;
//显式指定类型(为模板参数)
mySwap(a,b);
cout<< "a:"<< a<< "\tb:"<< b<< endl;
}
使用模板的注意事项- 在函数中,若多个参数使用模板,那么自动类型推导必须推导出一致的数据类型才可以使用
- 模板必须确定出T的数据类型才可以使用
普通函数调用时可以发生自动类型转换(隐式类型转换);函数模板调用时,若利用自动类型推导,则不会发生隐式类型转换,但若利用显式指定类型的方式则可以发生隐式类型转换
具体案例#includeusing namespace std;
templateT myAdd(T a, T b) {
return a + b;
}
void main() {
int a = 10;
char c = 'c';
//自动类型推导
//cout<< myAdd(a, c)<< endl;//报错,参数类型的指定必须一致,不能自动类型转换
//隐式指定类型
cout<< myAdd(a, c)<< endl;
//明确说明T的类型为int,传入的参数是int类型直接传,不是int类型则使用隐式类型转换转为int类型
}
普通函数与函数模板调用规则1.若函数模板与普通函数都可以调用,则优先调用普通函数
void myPrint(int a, int b) {
cout<< "调用普通函数"<< endl;
}
templatevoid myPrint(T a, T b) {
cout<< "调用函数模板"<< endl;
}
void main() {
int a = 10;
int b = 20;
myPrint(a, b);//调用普通函数
}
2.可以通过空模板参数列表的方式来强制调用函数模板
//只写了函数声明,没写函数实现
void myPrint(int a, int b);
templatevoid myPrint(T a, T b) {
cout<< "调用函数模板"<< endl;
}
void main() {
int a = 10;
int b = 20;
//通过空模板的参数列表强制调用函数模板
myPrint<>(a, b);
}
3.模板也可以实现函数重载
templatevoid myPrint(T a, T b) {
cout<< "调用函数模板1"<< endl;
}
//重载函数模板
templatevoid myPrint(T a, T b, T c) {
cout<< "调用函数模板2"<< endl;
}
void main() {
int a = 10;
int b = 20;
int c = 30;
//调用函数模板1
myPrint(a, b);
//调用函数模板2
myPrint(a, b, c);
}
4.如果函数模板可以产生更好的匹配,则优先使用函数模板
void myPrint(int a, int b) {
cout<< "调用普通函数"<< endl;
}
templatevoid myPrint(T a, T b) {
cout<< "调用函数模板"<< endl;
}
void main() {
char a = 'a';
char b = 'b';
//调用函数模板
myPrint(a, b);
}
注意:若提供了函数模板,那么最好就不要提供普通函数,否则容易出现二义性
模板的局限性templatevoid func(T a, T b) {
a = b;
}
注意:模板并不是万能的,该模板函数有一个局限性,若传入的a和b是一个数组,那么就无法实现了
具体化模板class Person {
public:
Person(string name, int age) {
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
templatebool myCompare(T& a, T& b) {
if (a == b) {
return true;
}
else {
return false;
}
}
//利用具体化(template<>)的Person版本来实现代码,具体化优先调用
template<>bool myCompare(Person & a, Person & b) {
if (a.m_Age == b.m_Age && a.m_Name == b.m_Name) {
return true;
}
else {
return false;
}
}
void main() {
Person p1("Tom", 10);
Person p2("Tom", 10);
bool ret = myCompare(p1, p2);
if (ret) {
cout<< "p1==p2"<< endl;
}
else {
cout<< "p1!=p2"<< endl;
}
}
解释:模板的类型若为Person类型,那么自动调用具体化了的方法
类模板 前言作用:建立一个通用的类,类中的成员,数据类型可以不具体指定,用一个虚拟的类型来代表
语法:
template类
解释:
- template:声明创建模板
- typename:表明其后面带符号的是一种数据类型(也可以用class替换)
- T:通用的数据类型,名称可以替换,通常为大写字母
1.类模板没有自动类型推导的使用方式
templateclass Person {
public:
Person(NameType name, AgeType age) {
this->m_Name = name;
this->m_Age = age;
}
NameType m_Name;
AgeType m_Age;
};
void main() {
//类模板的使用(显式指定类型)
Personp("叶秋", 25);
cout<< "p的name:"<< p.m_Name<< endl<< "p的age:"<< p.m_Age<< endl;
}
2.类模板在模板参数列表中可以有默认参数
//int为类模板的默认参数
templateclass Person {
public:
Person(NameType name, AgeType age) {
this->m_Name = name;
this->m_Age = age;
}
NameType m_Name;
AgeType m_Age;
};
void main() {
//类模板默认参数的使用
Personp("叶秋", 25);
cout<< "p的name:"<< p.m_Name<< endl<< "p的age:"<< p.m_Age<< endl;
}
类模板中成员函数创建时机- 普通类中的成员函数一开始就可以创建
- 类模板中的成员函数在调用时才可以创建
- 指定传入类型——直接显示对象的数据类型
- 参数模板化——将对象中的参数变为模板进行传递
- 整个类模板化——将这个对象类型模板化进行传递
templateclass Person {
public:
Person(NameType name, AgeType age) {
this->m_Name = name;
this->m_Age = age;
}
void showPerson() {
cout<< "姓名:"<< this->m_Name<< "\t年龄:"<< this->m_Age<< endl;
}
NameType m_Name;
AgeType m_Age;
};
//指定传入类型
void printPerson1(Person&p) {
p.showPerson();
}
//参数模板化
templatevoid printPerson2(Person&p) {
p.showPerson();
}
//整个类模板化
templatevoid printPerson3(P &p) {
p.showPerson();
}
void main() {
Personp("孙悟空", 100);
printPerson1(p);
printPerson2(p);
printPerson3(p);
}
类模板与继承
前言- 当子类继承的父类是一个类模板时,子类在声明的时候需要指定父类的类型
- 若不指定具体的类型,那么编译器无法给予子类分配内存
- 若想灵活指定父类中T的类型,子类也需要变成类模板
templateclass Base {
T m;
};
class Son:public Base{};
子类不指定具体类型案例templateclass Base {
T m;
};
templateclass Son:public Base{};
类模板成员函数的类外实现templateclass Person {
public:
Person(NameType name, AgeType age);
void showPerson();
NameType m_Name;
AgeType m_Age;
};
//构造函数的类外实现
templatePerson::Person(NameType name,AgeType age){
this->m_Name = name;
this->m_Age = age;
}
//成员函数的类外实现
templatevoid Person::showPerson() {
cout<< "姓名:"<< this->m_Name<< "\t年龄:"<< this->m_Age<< endl;
}
注意:类模板中的成员函数类外实现时需要加上模板的参数列表
类模板分文件编写 1.直接包含源文件person.h文件内
#pragma once
#includeusing namespace std;
templateclass Person {
public:
Person(NameType name, AgeType age);
void showPerson();
NameType m_Name;
AgeType m_Age;
};
person.cpp文件内
#include "person.h"
//构造函数的类外实现
templatePerson::Person(NameType name, AgeType age) {
this->m_Name = name;
this->m_Age = age;
}
//成员函数的类外实现
templatevoid Person::showPerson() {
cout<< "姓名:"<< this->m_Name<< "\t年龄:"<< this->m_Age<< endl;
}
执行文件内
//这里必须包含.cpp文件方可
#include "person.cpp"
void main() {
Personp("lili", 18);
p.showPerson();
}
执行文件不可以包含.h文件必须包含.cpp问件原因:类模板中的成员函数在调用时才可以创建
2.将.h和.cpp文件中的内容写到一起,后将后缀名改为.hpp文件person.hpp文件内
#pragma once
#includeusing namespace std;
templateclass Person {
public:
Person(NameType name, AgeType age);
void showPerson();
NameType m_Name;
AgeType m_Age;
};
//构造函数的类外实现
templatePerson::Person(NameType name, AgeType age) {
this->m_Name = name;
this->m_Age = age;
}
//成员函数的类外实现
templatevoid Person::showPerson() {
cout<< "姓名:"<< this->m_Name<< "\t年龄:"<< this->m_Age<< endl;
}
执行文件内
//这里必须包含.hpp文件
#include "person.hpp"
void main() {
Personp("lili", 18);
p.showPerson();
}
类模板与友元1.全局函数类内实现,直接在类内声明友元即可
templateclass Person {
//全局函数类内实现
friend void printPerson(Personp) {
cout<< "姓名:"<< p.m_Name<< "\t年龄:"<< p.m_Age<< endl;
}
public:
Person(T1 name, T2 age) {
this->m_Name = name;
this->m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
void main() {
Personp("lili", 18);
printPerson(p);
}
2.全局函数类外实现,需要让编译器知道该全局函数的存在
//编译器需要先知道printPerson函数的存在以及Person类的存在
template< class T1, class T2 >class Person;
templatevoid printPerson(Person< T1, T2 >p) {
cout<< "姓名:"<< p.m_Name<< "\t年龄:"<< p.m_Age<< endl;
}
templateclass Person {
//全局函数类外实现
//加空模板参数列表证明他是个模板函数
//若全局函数是类外实现,需要让编译器提前知道这个函数的存在
friend void printPerson<>(Personp);
public:
Person(T1 name, T2 age) {
this->m_Name = name;
this->m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
void main() {
Personp("lili", 18);
printPerson(p);
}
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
文章名称:C++之泛型编程-创新互联
本文来源:http://ybzwz.com/article/gopcg.html