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

网站的网络推广营销的本质

网站的网络推广,营销的本质,网站推广怎么推广,简单个人网页制作目录 一、前言 二、非类型模板参数 三、模板的特化 3.1 类模板特化 3.11 全特化 3.12 偏特化 3.2 函数模板特化 3.3 注意 四、模板的分离编译 一、前言 前面的文章梳理了模板初阶的一些用法,在后面梳理了STL的一些容器的用法后,下面将用到含有S…

目录

一、前言

二、非类型模板参数

三、模板的特化

3.1 类模板特化

3.11 全特化

3.12 偏特化

3.2 函数模板特化

3.3 注意

四、模板的分离编译


一、前言

前面的文章梳理了模板初阶的一些用法,在后面梳理了STL的一些容器的用法后,下面将用到含有STL的模板部分知识进行梳理。

那么首先我们先看下面的代码:

template<class Container>
void Print(const Container& con)
{Container::const_iterator it=con.begin();while(it != con.end()){cout << *it << " ";it++;}cout << endl;
}int main()
{vector<int> v;v.push_back(1);v.push_back(2);Print(v);
}

这里我们首先实例化了一个vector<int>的对象v,然后插入两个数据,最后写了一个打印函数来打印有迭代器的容器的数据,但这里我们运行后出现了上图的错误,这个错误出现的原因是第四行我们使用模板导致的,因为在我们使用模板进行定义时,在没有对它进行实例化前编译器无法识别,在没有实例化时,Container::const_iterator这一个定义,编译器无法识别,因为这一句话既可以当作类型,也可以当作变量/对象,虽然作为变量时加上后面的it是不对的,但编译器无法在没有其他任何操作前正确识别,所以报错了。那么我们想要解决这个问题只要提前告诉编译器这是类型就可以了,这里用到了定义模板参数时的另一个与class同等效果的typename,typename在模板中与class唯一的不同就在于将typename提前可以告诉编译器这句话是代表类型,这样编译器就会在识别时确定这是类型,就不会报错了。

template<class Container>
void Print(const Container& con)
{typename Container::const_iterator it=con.begin();while(it != con.end()){cout << *it << " ";it++;}cout << endl;
}int main()
{vector<int> v;v.push_back(1);v.push_back(2);Print(v);
}

类似上面这样的只要传过来的容器含有模板参数(vector<T>这样的也是)都要在前面加typename

注意:无论定义模板参数时是class还是typename,遇到上面这种模板参数来定义时都要在定义前加typename

二、非类型模板参数

首先我们知道模板的使用格式是

template<class (模板参数),    ...>

那么非类型模板参数就是在模板参数的定义中用常量来代表模板参数。

下面我们写了一个静态栈的代码:

#define N 10
template<class T>
class Stack
{
private:T _a[N];int _top;
};
int main()
{Stack<int> st1;Stack<int> st2;
}

如果此时我们需要st1的大小为10,st2的大小为100,如何做?此时我们发现一个静态栈已经无法实现了,那么此时只要我们用到非类型模板参数加一个非类型模板参数即可:

template<class T,size_t N>
class Stack
{
private:T _a[N];int _top;
};
int main()
{Stack<int,10> st1;Stack<int,100> st2;
}

上述代码所示:我们在模板参数中加了一个非类型模板参数,这样我们在实例化时只要填我们需要的常量时就可以了。

注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
2. 非类型的模板参数必须在编译期就能确认结果。

三、模板的特化

在实际应用中会遇到一些普通模板无法实现的情况,需要特殊处理,那么此时就可以使用模板的特化来特殊处理。(这里以梳理用法为主)

模板的特化分为函数模板特化和类模板特化

3.1 类模板特化

3.11 全特化

全特化就是将所有模板参数特殊化,格式如下:

template<>

class A<类型,类型...>

{};

全特化将<>中的所有模板参数去掉,将我们需要特化的类型放到类名后面的<>中

我们看下面的代码:

//没有特化
template<class T1,class T2>
class Data
{
public:Data(){cout << "Data<T1, T2>" << endl;}
private:T1 d1;T2 d2;
};
//全特化
template<>
class Data<int, char>
{
public:Data(){cout << "Data<int,char>" << endl;}
private:int d1;char d2;
};
int main()
{Data<int ,int> d1;Data<int, char> d2;
}

这串代码中上面是没有特化的,下面是全特化,全特化这里我们需要int和char型,所以将类型写到Data后即可,那么此时我们只有在调用时以Data<int, char> d2 ;这样的格式才可以使用全特化,<int,int>在这里只能调用没有特化类

3.12 偏特化

偏特化就是特化部分模板参数或进一步限制模板参数。

template<class T1,class T2>
class Data
{
public:Data(){cout << "Data<T1, T2>" << endl;}
private:T1 d1;T2 d2;
};
//偏特化1:特化部分模板参数
template<class T1>
class Data<T1, int>
{
public:Data(){cout << "Data<T1, int>" << endl;}
private:T1 d1;int d2;
};
//偏特化2:进一步限制模板参数
template<class T1, class T2>
class Data<T1*,T2*>
{
public:Data(){cout << "Data<T1*, T2*>" << endl;}
private:T1* d1;T2* d2;
};

偏特化有两种,偏特化1:特化部分模板参数和偏特化2:进一步限制模板参数,它们代表着两种偏特化形式:

偏特化1:将部分模板参数特化,上述代码中我们可以看到保留了一个模板参数T1,特化了一个模板参数成int。

偏特化2:这里保留了所有的模板参数,但将所有的模板参数进一步进行限制.。例如上述代码中将所有的模板参数限制为指针,也就是说只要参数都是指针类型的都会去调用这个模板类。

3.2 函数模板特化

函数模板只有全特化

#include<stdbool.h>
//没有特化
template<class T>
bool Less(T a, T b)
{return a < b;
}
//全特化
template<>
bool Less<Date*>(Date* a, Date* b)
{return *a < *b;
}int main()
{cout << Less(1, 2) << endl;Date d1(2022, 7, 7);Date d2(2022, 7, 8);Date* p1 = &d1;Date* p2 = &d2;cout << Less(p1, p2) << endl;
}

上述代码中先写了一个Less没有特化的比较,当遇到像Date* p1=&d1这样的变量时再使用普适模板就无法比较了,所以需要写一个Less模板的特化将Date*单写出来

bool Less(Date* a, Date* b)
{return *a < *b;
}

上述代码中没有使用模板但依然可以正常比较,大部分的函数模板都可以被不适用模板的函数代替,所以此时再使用模板就会降低运行效率,因此函数模板的特化在此时没有必要使用。

3.3 注意

无论是类模板特化还是函数模板特化,在使用特化时必须要有普通模板的存在,不然会报错。

四、模板的分离编译

我们有时会为了方便将函数的声明和定义分离,将声明放到头文件中,定义放到源文件中,但如果使用了模板后那么这个函数就不可以与普通函数一样放到两个文件中。

我们看下面代码:

//Stack.h
namespace lbs
{template<class T, class container = vector<int>>class stack{public:void push(const T& val);void pop();T& top(){return _con.back();}size_t size(){return _con.size();}private:container _con;};
//-------------Stack.cpp---------------------------
namespace lbs
{template<class T, class container>void stack<T, container>::push(const T& val){_con.push_back(val);}template<class T, class container>void stack<T, container>::pop(){_con.pop_back();}//template class stack<int>;
}
//-----------------test.cpp-------------------------
int main()
{lbs::stack<int> st1;st1.push(1);st1.pop();
}

上述代码中,我们在Stack.h文件中我们写了一个stack类,其中push和pop进行了声明与定义分离,size和top没有进行分离,此时我们运行后在定义的push和pop处会报错。

这里出现错误的原因就是在链接过程中编译器无法正确识别类模板的实例化,因为这里出现了模板参数,而模板参数在改函数没有被调用时不会实例化,所以链接阶段没有进行实例化,那么此时在Stack,cpp文件中的定义就无法正常进行。

想要正确分离有两种方法:

1、较为麻烦(不推荐)

在Stack.cpp文件中加上template class stack<类型>;这一句话

在定义所在文件中加上这一句话就代表提前告诉编译器要对此类型进行实例化,但麻烦的地方在于每此用新的类型时都要加上这一句话并填上对应的类型

2、较为简单(推荐)

namespace lbs
{template<class T, class container = vector<int>>class stack{public:void push(const T& val);void pop();T& top(){return _con.back();}size_t size(){return _con.size();}private:container _con;};template<class T, class container>void stack<T, container>::push(const T& val){_con.push_back(val);}template<class T, class container>void stack<T, container>::pop(){_con.pop_back();}
}

将定义放到声明的下方,此时声明与定义分离

http://www.dtcms.com/wzjs/836491.html

相关文章:

  • 南阳网站设计招聘网站套餐
  • 中国建设教育协会网站培训中心黑科技软件合集网站
  • 大型网站运维公司linux部署wordpress
  • 网站建设目标的文字河北省做网站的企业
  • 中文网站建设公司游戏推广平台有哪些
  • 网站导航图怎么做的详细步骤昆明网站建设方案报价
  • 个体做外贸的网站wordpress直接
  • app开发制作平台网站建设汕头建设网招标
  • 适合做浏览器主页的网站怎么用阿里云服务器做网站
  • 一级a做爰片免费网站 新闻上海关键词优化按天计费
  • 个人或主题网站建设一学一做短视频网站
  • 游戏咨询网站建设目标是什么公司网站建设需要收集什么信息
  • 凡科网站怎么做建站安徽省建设厅八大员报名网站
  • 如何做婚介网站python编程语言的特点
  • 然后在亚马逊网站上做外贸什么网站建设比较好的
  • 企业网站管理系统设计报告广州市 住房建设局网站
  • 普通建站湛江在线网
  • 网站做百科高校二级网站建设要求
  • discuz培训网站模板下载江西医院网站建设
  • 设计素材网站月收益成都市建设领域信用系统网站
  • 邻水网站建设iis 里没有网站吗
  • 营销型网站制作价格建小公司网站
  • 网站建设首期款个人简历模板可编辑免费
  • 高端品质网站建设wordpress怎样上传目录本
  • 自适应网站一般用什么框架做企业所得税计算公式怎么算
  • 企业网站怎样做优化打码网站如何建设
  • 建设局网站查询个人信息外贸社交网站排名
  • 物流网站怎么做推广营销推广有哪些公司
  • 杭州手机网站开发wordpress更改图片链接
  • 深圳企业营销型网站建设海南省建设集团有限公司