当前位置: 首页 > news >正文

全球建筑网站关键词优化案例

全球建筑网站,关键词优化案例,网站引流怎么做的,个人网页设计作品手绘目录 1、泛型编程 2、函数模板 2.1、函数模板概念 2.2、函数模板格式 2.3、函数模板的原理 2.4、函数模板的实例化 2.6、模板参数的匹配原则 3、类模板 3.1、 类模板的定义格式 3.2、 类模板的实例化 4、非类型模板参数 5、模板的特化 5.1、函数模板特化 5.2、类模…

目录

1、泛型编程

2、函数模板

2.1、函数模板概念

2.2、函数模板格式

2.3、函数模板的原理

2.4、函数模板的实例化

2.6、模板参数的匹配原则

 3、类模板

3.1、 类模板的定义格式

3.2、 类模板的实例化

4、非类型模板参数

5、模板的特化 

5.1、函数模板特化

 5.2、类模板特化

5.2.1、全特化

5.2.2 、偏特化

 6、模板分离编译


1、泛型编程

我们平时如何实现一个通用的交换函数

void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}
void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}
使用函数重载虽然可以实现,但是有一下几个不好的地方:
  • 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
  • 代码的可维护性比较低,一个出错可能所有的重载均出错

 我们在平时在生活中要使用一个红色的字案,我们没有必要把他直接做出来,我们可以做出一个印章,在使用印章时我们可能需要使用不同的颜色,我们就给出不同的颜色,这就是模具

​ 

那我们是否也可以在c++中,也有一个这样的模具,通过给这个模具不同的类型,来生成具体的代码。 在c++中也有像这样的模具,就是模板

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础

2、函数模板

2.1、函数模板概念

函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能

2.2、函数模板格式

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表)
{//....}
template<typename T>
void Swap( T& left, T& right)
{T temp = left;left = right;right = temp;
}
注意: typename 用来定义模板参数 关键字 也可以使用 class( 切记:不能使用 struct 代替 class)
template<class T>
void Swap( T& left, T& right)
{T temp = left;left = right;right = temp;
}

2.3、函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模 板就是将本来应该我们做的重复的事情交给了编译器
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于整型类型也是如此。

 

2.4、函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:
  • 隐式实例化
  • 显式实例

 1. 隐式实例化:让编译器根据实参推演模板参数的实际类型

 2. 显式实例化:在函数名后的<>中指定模板参数的实际类型

 1. 隐式实例化:让编译器根据实参推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}int main()
{int a1 = 10, a2 = 20;double d1 = 10.0, d2 = 20.0;Add(a1, a2);Add(d1, d2);return 0;
}
  Add(a1, d1);/*该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅*/// 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化Add(a1, (int)d1);

 2. 显式实例化:在函数名后的<>中指定模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}int main()
{int a1 = 10;double d1 = 10.0;Add<int>(a1,d1);return 0;
}

2.6、模板参数的匹配原则

1、 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板 

2、一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函

3、模板函数不允许自动类型转换,但普通函数可以进行自动类型转换 

// 专门处理int的加法函数
int Add(int left, int right)
{return left + right;
}template<class T>
T Add(T left, T right)
{return left + right;
}int main()
{Add(1, 2);         // 与非模板函数匹配,编译器不需要特化Add<int>(1, 2);    // 调用编译器特化的Add版本Add(1.0, 1.0);     // 调用编译器特化的Add版本return 0;
}

 相信大家看到这里还是有点懵,接下来我给大家讲一个小故事:

有一天中午,小明肚子饿了,他想吃面条,刚好楼下有一家面馆,然后家里的柜子里有还没做好的面条,小明是个懒鬼,就直接下楼吃去了

第二天,小明肚子又饿了,他想吃大盘鸡,楼下没有,家里的柜子里有还没做好的鸡,现在小明没得选了,只能自己做了

编译器也一样,已经有非模板函数的参数类型和我的类型匹配,编译器就不会再去自己做了(自己实例化),如果没有非模板函数的参数类型和我的类型匹配,那么编译器才会去自己实例化


 3、类模板

3.1、 类模板的定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};
template<class K,class V>
struct AVLTreeNode
{AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;              pair<K, V> _kv;                          // 存储的键对int _bf;                                 // balance factorAVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv);bool IsBalance();void InOrder();void Height();void Size();private:void RotateL(Node* parent);              //左旋转void RotateR(Node* parent);              //右旋转void RotateRL(Node* parent);             //右左旋转void RotateLR(Node* parent);             //左右旋转bool _IsBalance(Node* root);void _InOrder(Node* root);int _Height(Node* root);int _Size(Node* root);Node* _root = nullptr;
};
注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template<class K, class V>
void AVLTree<K, V>::Size()
{cout << _Size(_root) << endl;
}

3.2、 类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类
AVLTree<int,int> s;

4、非类型模板参数

        模板参数: 
  • 类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称
  • 非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该数当成常量来使
template<class T, size_t N = 10>class array{public:T& operator[](size_t index){return _array[index];}const T& operator[](size_t index)const{return _array[index];}size_t size()const{return _size;}bool empty()const{return 0 == _size;}private:T _array[N];size_t _size;};
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
2. 非类型的模板参数必须在编译期就能确认结果

5、模板的特化 

在原模板类的基础上,针对特殊类型所进行特殊化的实现方式
模板特化中分为函数模板特化与类模板特化

5.1、函数模板特化

  1. 必须要先有一个基础的函数模板
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参表: 必须要和模板函数的基础参数类型完全相同

class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){}bool operator<(const Date& d) const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d) const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}
private:int _year;int _month;int _day;
};
template<class T>
bool Less(T left, T right)
{return left < right;
}// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{return *left < *right;
}int main()
{cout << Less(1, 2) << endl;Date d1(2023, 11, 19);Date d2(2022, 11, 20);cout << Less(d1, d2) << endl;Date* p1 = &d1;Date* p2 = &d2;cout << Less(p1, p2) << endl;return 0;
}

 5.2、类模板特化

template<class T1, class T2>
class Data
{
public:Data() {cout<<"Data<T1, T2>" <<endl;}
private:T1 _d1;T2 _d2;
};

5.2.1、全特化

template<>
class Data<int, char>
{
public:Data() {cout<<"Data<int, char>" <<endl;}
private:int _d1;char _d2;
};

5.2.2 、偏特化

偏特化有以下两种表现方式:
  • 部分特化 :将模板参数类表中的一部分参数特化
  • 参数更进一步的限制:偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本

1、部分特化 :将模板参数类表中的一部分参数特化

// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:Data() {cout<<"Data<T1, int>" <<endl;}
private:T1 _d1;int _d2;
};

2、参数更进一步的限制:偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本

//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{ 
public:Data() {cout<<"Data<T1*, T2*>" <<endl;}private:
T1 _d1;T2 _d2;
};//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:Data(const T1& d1, const T2& d2): _d1(d1), _d2(d2){cout<<"Data<T1&, T2&>" <<endl;}private:const T1 & _d1;const T2 & _d2; };

 6、模板分离编译

模板尽量不要分离编译

C/C++程序要运行,一般要经历一下步骤:预处理—-->编译—-->汇编—-->链接
1、编译:对程序按照语言特性进行词法、语法、语义分析,错误检查无误后生成汇编代码
        注意头文件不参与编译编译器对工程中的多个源文件是分离开单独编译的。
2、链接:将多个obj文件合并成一个,并处理没有解决的地址问题

 

  • 在.cpp文件中,编译器没有看到对模板函数的实例化,因此,不会生成具体的函数
  • 在main. obj中调用的函数,编译器在链接时才会找其地址,但是这两个函数没有实例化没有生成具体代码,因此链接时报错
解决方法
1. 将声明和定义放到一个文件 "xxx.hpp" 里面或者 xxx.h 其实也是可以的
2. 模板定义的位置显式实例化

http://www.hkea.cn/news/823004/

相关文章:

  • 团购的网站扣佣金分录怎么做厦门百度竞价
  • 国家疫情最新政策麒麟seo外推软件
  • 河南第二波疫情最新消息淘宝关键词优化技巧教程
  • 优化好的网站做企业网站百度代理公司
  • 外贸b2c网站如何做推广百度电话人工服务
  • 百度怎样做网站并宣传网站2023上海又出现疫情了
  • wordpress后台登录慢阳山网站seo
  • 深圳网站建设企网络推广运营途径
  • 给自己女朋友做的网站yandex搜索引擎
  • 购物网站建设教程怎么在网上做广告宣传
  • 冠县做网站推广网站怎么制作
  • 开封 网站建设苹果被曝开发搜索引擎对标谷歌
  • 东莞虎门高铁站百度客户端电脑版下载
  • 建网站怎么挣钱的学seo推广
  • 自如网站做的好 服务哪个网站学seo是免费的
  • 国外网站阻止国内访问怎么做竞价推广工具
  • 建设一个网站需要哪些方面的开支百度人工客服
  • 品牌网站建设-建站之路最新疫情新闻100字
  • 东莞网站优化科技有限公司怀柔网站整站优化公司
  • 郑州网站建设联系方式外链是什么意思
  • 用wordpress做网站教程电脑优化大师有用吗
  • 佛山企业网站制作今日热点新闻事件
  • 企业网站网络推广黑帽seo培训
  • 欧美做的爱爱网站有哪些广告推广赚钱
  • 泉州网站建设工作室谷歌seo价格
  • 国建设委员会网站百度推广一天烧几千
  • 做网站 花园路国贸营销推广方案包括哪些内容
  • 做商城网站哪里买口碑营销属于什么营销
  • 鞋子 东莞网站建设真正的免费建站在这里
  • 网站上微信的链接怎么做项目平台