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

做网站后期续费是怎么算的视频封面制作网站

做网站后期续费是怎么算的,视频封面制作网站,找大连做企业网站的公司,网站建设没业务CSDN的uu们#xff0c;大家好。这里是C入门的第十四讲。 座右铭#xff1a;前路坎坷#xff0c;披荆斩棘#xff0c;扶摇直上。 博客主页#xff1a; 姬如祎 收录专栏#xff1a;C专题 目录 1. 知识引入 2. 模板的使用 2.1 函数模板 2.2 类模板 3. 模板声明和定义… · CSDN的uu们大家好。这里是C入门的第十四讲。 · 座右铭前路坎坷披荆斩棘扶摇直上。 · 博客主页 姬如祎 · 收录专栏C专题 目录 1. 知识引入 2. 模板的使用 2.1 函数模板 2.2 类模板 3. 模板声明和定义分离 3.1 同一文件中的声明与定义分离 3.2 分文件的声明与定义分离 4. 非类型模板参数 5. 模版的特化 5.1 模板的全特化 5.2 模板的偏特化 6. 模板总结 1. 知识引入 有一天我们在写C语言程序的时候想要交换两个数的值于是我们很快就写了一个交换两个整形变量的函数 void Swap(int x, int y) {int tmp x;x y;y tmp; } 但是写了一会代码你发现你又要交换两个double的值你又要重新写一个Swap double的函数。假如后来你还需要交换其他类型的变量那么你就需要写更多的Swap函数。是不是偷一下子就变大了。不过别慌C带着新的语法走来了 2. 模板的使用 听到模板这个名词我们就想到了显示生活中的模具通过一个模具我们就能制作出很多产品。同理通过一个模板我们就能实现很多功能满足你的各种需求C的模板是泛型编程的基础所谓泛型编程编写与类型无关的通用代码是代码复用的一种手段。 我们来看看模板的语法 template typaname T1, typename T2, ··· , typaname TN 函数/类 模板通过关键字 template 来定义template 后面紧跟一个 尖括号  尖括号中加上关键字 typename (typename 换成class也行) 然后跟上模板参数其中尖括号中的写法与函数的形参列表极为相似。其中的T1T2 ··· 叫做模板参数名字可以随意更改。根据template下方定义的类型模板可以分为函数模板与类模板。 2.1 函数模板 我们先来看看函数模板的用法吧我们就拿上面的Swap函数来试试吧看看有了函数模板能省事多少 //定义函数模板 templatetypename T void Swap(T x, T y) {T tmp x;x y;y tmp; } 模板起始就是将类型参数化在上面的代码中我们将Swap函数的参数类型用模板参数代替当我们调用函数时编译器会根据传入参数的类型自动为T实例化出对应的类型 通过调试发现即使我们传入不同类型的参数也能够做到交换两个变量的值。 你可能会好奇编译时怎么做到的呢其实是这样的当你使用 int 类型调用 Swap 函数那么编译器就会根据函数模板生成一个参数类型为 int 的函数当你使用 double 类型调用 Swap 函数那么编译器就会根据函数模板生成一个参数类型为 double 的函数。你可能会说这和直接些两个函数没有什么区别啊但事实时我们只写了一个函数模板多余的事儿我们都交给了编译器这不香吗 通过观察汇编代码可以看到确实是生成了连个不同参数类型的函数 在C中通过函数模板生成函数的过程我们叫做模板的实例化。 上面我们使用函数模板的方式叫做隐式实例化 即不指定模板参数的类型编译器根据参数的类型自动推导模板参数的类型。 但是并不是所有的情况都能通过隐式实例化来完成那个时候就必须显示实例化啦 templatetypename T T* alloc(size_t n) {return new T[n]; }int main() {int* a1 alloc(10);//显示实例化int* a2 allocint(10);return 0; } 隐式实例化是会报错的因为他无法通过你传入的参数推导出模板参数T的实际类型。  2.2 类模板 类模板和函数模板差不多只不过定义函数的地方改成定义类。 在下面的代码中我们定义了一个名为Stack的模板类根据模板实例化时传入的模板参数的类型不同我们就能实例化出来栈内元素类型不同的栈。在C语言中我们只能通过 typedef 来实现变换栈内元素的类型但是确做不到在一个工程中同时使用 一个数据元素是 int 的栈 一个数据元素是 double 的栈(除非你不嫌麻烦赋值一份栈的代码)。但是有了类模板就能轻松做到。 templatetypename T class Stack { public:private:T* _a;int _size;int _capacity; };int main() {Stackint st1;Stackdouble st2; } 我们可以看到类模板在实例化的时候就只能显示实例化了没法隐式实例化呢即使你能够通过类中的构造函数推导出模板参数的类型 也不能隐式实例化呢这是为什么呢第 3 点会给你答案。 3. 模板声明和定义分离 3.1 同一文件中的声明与定义分离 我们来看全局的函数模板的声明与定义分离该怎么书写 //函数模板的声明 templatetypename T void Swap(T x, T y);//函数模板的定义 templatetypename T void Swap(T x, T y) {T tmp x;x y;y tmp; } 在声明的时候需要有 templatetypename T 在定义的时候也需要有 templatetypename T 因为模板参数只能在它下面的第一个函数或者类中使用。 相比全局函数实现 声明与定义分离我们更喜欢用的是类的成员函数的声明与定义分离 我们在类中声明了一个push函数虽然我们在外面实现了push函数但是编译器依然报错说明我们实现的方式有问题你可能会说加一个类域很棒但是还是不完全正确在解决这个问题之前还需要铺垫一个知识普通类的类名即是一个类型但是模板类的类名还是一个类型吗我都这样说了你肯定知道不是啦的确不是模板类的类型需要显示指定模板参数才是该类的类型。 像这样Stackint 这就是一个Stack类型。 ok我们现在大概能猜出类成员函数的声明与定义分离应该怎么写了吧使得还需要在函数名的前面加上这个类的类型才行 。 templatetypename T class Stack { public:int size(){return _size;}void push(const T val);private:T* _a;int _size;int _capacity; };templatetypename T void StackT::push(const T val) {_a[size] val; }像上面这样我们就实现了类成员函数的声明与定义分离了呢在实际的编程中我们习惯将那些短小的函数直接在类内定义(默认就是内联函数了)那些比较长的函数实现声明与定义分离。  现在我们就知道为什么模板类不可能隐式实例化了嘛因为模板类的类名不是类型必须指定模板参数后才是类型只有用类型才能定义变量 3.2 分文件的声明与定义分离 我们在写C语言的时候就喜欢将函数的定义与声明分文件编写嘛现在我们来看看模板类的成员函数如果声明与定义分文件编写会发生什么 //test.h / // #pragma once templatetypename T class Stack { public:Stack(int capacity 4){_a new T[capacity];_size 0;_capacity capacity;}int size(){return _size;}void push(const T val);void pop();private:T* _a;int _size;int _capacity; };/// /// test.cpp / ///#includetest.htemplatetypename T void StackT::push(const T val) {_a[_size] val; }templatetypename T void StackT::pop() {_size--; }/// /// main.cpp / /// #includeiostream #includetest.husing namespace std;int main() {Stackint st;st.size(); // 不会出问题st.pop();st.push(1);}还有一个奇怪的事儿就是当你注释掉 push 和 pop 函数的调用就不会报错了这是因为 模板 函数会按需实例化 当你没有调用这个函数时 编译器是不会实例化出来对应的函数的  我们发现调用 push 和 pop 函数会报链接错误。这是为啥呢链接时错误一般都是在函数有声明没有定义的时候出现的但是我在 test.cpp 确实是定义了 push 和 pop 函数的啊 我们慢慢来分析size函数没有报错是因为size函数在声明的时候直接就定义了编译的时候就能直接确定函数的地址。但是对于 push 和 pop 函数因为他们的定义在另一个文件只有在链接的时候才能确定函数的地址当链接的时候去找 push 和 pop 函数的地址没找到因此报了链接错误。 为什么就没找到呢 是因为我们的 push 与 pop 的实现在另一个文件在模板函数所在的cpp文件不知道模板参数的具体类型编译器不知道该实例化什么模板参数是什么类型的函数从而无法为这两个函数确定函数地址。链接的时候自然就找不到这两个函数的地址了 该怎么解决这个问题呢 我们可以在 push 与 pop 所在的文件中显示实例化模板参数告诉编译器模板参数的类型 告诉编译器帮我实例化模板参数为int 的函数但是如果我们用到了 Stackdouble 那么我们还需要在这个文件中显示实例化模板参数为 double的函数 因此 在实际的编程中我们更喜欢将模板类的类成员函数的声明与定义放在同一个文件里面有的人为这样的文件取名为 .hpp 文件用来标识这是一个模板类 为什么在同一个文件里面实现定义与分离就不会报错呢我们在cpp文件中使用这个类都需要包含这个类的头文件包含这个头文件之后我们就在一个cpp文件里面同时有了函数的声明与定义。当我们使用这个模板类肯定会传入模板参数从而确定了模板参数的类型编译过程中那些定义的函数就知道了模板参数的类型只需要根据模板参数的类型实例化函数即可 4. 非类型模板参数 模板的参数不仅仅可以通过 typename T 将类型参数化。还允许使用整形值充当模板参数(这里的整形值指的是整形家族例如 intcharunsigned int 等) 这有什么作用呢 现在需要你实现一个静态栈并且要求多个静态栈的大小要不相同你会怎么做呢使用#define 栈的大小能解决问题嘛显然#define 和上面的typename 陷入了一样的困境当实例化多个时都无法实现我们的需求那看看非类型模板参数是怎么做的吧 templatetypename T, size_t N class Stack { public:private:T _a[N];int _size;int _capacity; };int main() {Stackint, 100 st1; // 空间大小为 100 的静态栈Stackint, 10 st2; // 空间大小为 10 的静态栈} 其中那个 N 就是非类型的模板参数 观察到 N 可以直接用来当作数组的大小。因此这个 N 是一个常量哦不允许被修改。 下面补充一下 typename 的另一层用途 我定义了一个类List然后 ListT 中将 ListNodeT typedef 一下。在类 B 中我们尝试去取ListT 中的 Node 来定义一个变量发现报出了编译错误这是为什么呢 原因就在于向模板类里面取东西编译器无法确定你取的东西是一个类型还是一个对象(例如静态成员变量)假设你取的是一个类型那么 ListT::Node _node就不会报错单如果你取的是一个对象这条语句就是有问题的所以为了明确你取的东西需要加上typename告诉编译器你取的是一个类型 这个语法在我后面实现STL容器时会用到 5. 模版的特化 来看下面的代码我们实现了一个打印的函数模板传入什么值就打印什么值于是我们写出了这样的代码 templatetypename T void Print(const T val) {cout val endl; } 打印都没有问题但是我有这样一个需求就是当你传入指针的时候我希望打印的是指针指向的内容而不是打印指针本身这个时候应该怎么做呢这就要使用我们的模板特化了 通常情况下使用模板可以实现一些与类型无关的代码但对于一些特殊类型的可能会得到一些错误的结 果需要特殊处理比如实现了一个专门用来进行小于比较的函数模板 5.1 模板的全特化 顾名思义全特化就是将模板参数全部都特化成具体的类型。 函数模板的特化步骤 1. 必须要先有一个基础的函数模板 2. 关键字template后面接一对空的尖括号 3. 函数名后跟一对尖括号尖括号中指定需要特化的类型 4. 函数形参表: 必须要和模板函数的基础参数类型完全相同如果不同编译器可能会报一些奇怪的错误。 比如上面的例子我们将模板参数T特化当传入指针类型的时候我们打印指针指向的内容。 templatetypename T void Print(const T val) {cout val endl; }templatetypename T void Print(T* val) {cout (*val) endl; }int main() {Print(5);int a 10;Print(a);double b 20.5;Print(b); } 注意一般情况下如果函数模板遇到不能处理或者处理有误的类型为了实现简单通常都是将该函数直接给出。 该种实现简单明了代码的可读性高容易书写因为对于一些参数类型复杂的函数模板特化时特别给出因此函数模板不建议特化  我们来看看模板类的全特化 templateclass T1, class T2 class Show { public:Show(){cout Show(T1, T2) endl;} };template class Showint, int { public:Show(){cout Show(int, int) endl;} };template class Showint, double { public:Show(){cout Show(int, double) endl;} };int main() {Showdouble, double s1;Showint, int s2;Showint, double s3; } 我们看到我们写了特化之后就能针对指定的类型进行特殊处理了 5.2 模板的偏特化 模板的偏特化就是值针对一部分模板参数进行特化 templateclass T1, class T2 class Show { public:Show(){cout Show(T1, T2) endl;} };templateclass T1 class ShowT1, int { public:Show(){cout Show(T1, int) endl;} };templateclass T1 class ShowT1, double { public:Show(){cout Show(T1, double) endl;} };int main() {Showdouble, double s1;Showint, int s2;Showint, double s3; } 总之模板的特化能够使得我们更加方便的处理特殊化的情况。这一点在我们实现STL中的优先级队列会提到 6. 模板总结 【优点】 1. 模板复用了代码节省资源更快的迭代开发C的标准模板库(STL)因此而产生。 2. 增强了代码的灵活性。 【缺陷】 1. 模板会导致代码膨胀问题也会导致编译时间变长。其实这个问题不可避免如果没有模板那么就需要你手写这么多的代码了 2. 出现模板编译错误时错误信息非常凌乱不易定位错误。(这个是真的令人头大)
http://www.pierceye.com/news/318807/

相关文章:

  • 免费手机网站商城微信公众号对接网站做
  • 用vs2013做网站公司网站突然404
  • 东莞建站模板搭建广东商城网站建设
  • crm网站下载网站建设网址网站制作
  • 网站开发怎么入驻京东花店网站开发参考文献
  • 郑州专业网站推广优化公司技术支持 东莞网站建设
  • 苏州做网站的公司哪家最好网站企业
  • 厦门做网站seo网络营销就是什么
  • 哪个网站可以学做蛋糕网络软件系统
  • 网站制作的核心要点是什么找人做网站服务器不是自己的怎么办
  • 自己做国际网站福建省文明建设办公室网站
  • 天津专业做网站的公司私人免费网站怎么下载
  • 深圳网站设计灵点网络口碑好广州海珠建网站
  • 网站开启gzip压缩西安的推广公司
  • 深圳彩票网站建设企业邮箱免费版开通
  • 佛山网站建设网络推广wordpress文章加音频
  • 设计师新手接单网站怎么把自己做的网站
  • 动漫制作专业在国企河北网络营销推广seo
  • 潜江网站建设兼职万网人网站备案流程
  • 物流官网网站今天新闻联播
  • 郑州网站开发的公司三亚今天最新通知
  • 足球直播网站怎么做东莞市公司网站建设平台
  • 建设网站需要了解什么校园网站建设和管理工作制度
  • 网站商务通弹出窗口图片更换设置移动端cpu
  • 成都画册设计的公司海外seo托管
  • 中国早期互联网公司河南seo网站开发
  • wordpress添加短代码优化营商环境的金句
  • 网站访问统计js代码wordpress后台登陆不进去
  • dede 网站版权信息互联网平面设计
  • 可以做试卷的网站看书网站排名