小工具知识网

当前位置: 首页 > 行业知识 > C++:模板

行业知识

C++:模板

2026-10-30 23:34:14 来源:互联网转载

C++:模板

    • 函数模板
      • 显式实例化
      • 模板参数缺省
      • 参数匹配规则
      • 类模板
        • 类名与类型
        • 类成员的声明定义分离
        • 非类型模板参数
        • 模板特化
          • 函数模板特化
          • 类模板特化
            • 全特化
            • 偏特化
              • 部分特化
              • 限制���化

                在讲解模板前,我提出一个问题:

                ()

                如何实现一个通用的swap交换函数?

                也许你可以这样:

                ()
                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;}......

                把每种类型都进行重载,写出n多种交换函数。

                但这很明显是一个费力不讨好的方法,不仅会让代码冗余重复,而且写出这样的代码,也会耗费精力。

                那么有没有一种办法,我们给编译器一个模板,编译器自动生成函数?

                C++就样提供了模板,而C++最重要的STL库,也就是起源于模板的。

                模板分为函数模板与类模板,我们先通过函数模板来了解模板的大部分规则:

                函数模板

                功能:

                函数模板代表了一个函数家族,在使用时被参数化,根据实参的类型生成特定类型的版本

                也就是说,我们可以通过一个函数模板,让编译器生成一整个同类型的函数家族。

                语法:

                template 
                template 

                而被class和typename定义是模板参数,它可以被任意类型代替。如果你不能理解,我们不妨看看示例。

                示例:

                template T Add(T x, T y){return x + y;}
                int Add(int x, int y){return x + y;}

                这个函数是不是很熟悉了?

                也就是说,T是可以被替换的类型,那么我们要如何确定这个T的类型?

                编译器会根据调用函数时传入的参数,自动判断类型。

                比如以下调用:

                Add(1, 5);Add(3.0, 5.0);

                对于Add(1, 5);,其两个参数都是int类型,那么此时模板就会生成一个int类型的Add函数。

                对于Add(3.0, 5.0);,其两个参数都是double类型,此时模板就会生成一个double类型的Add函数。

                以此类推,我们不论想要多少种类型,只需要传入参数,让编译器自动识别,而我们只需要写一个模板,就可以衍生出无数种函数,这就是模板的优势。

                那么我们现在来实现一下一开始swap函数的模板:

                template void Swap(T& left, T& right){T temp = left;left = right;right = temp;}

                不过要注意,模板只是一个蓝图,本身不是函数,当我们传入指定类型参数,其就会生成相应的函数。


                显式实例化

                再回到刚刚的Add函数模板。

                template T Add(T x, T y){return x + y;}

                如果我们传入两个不同类型的参数怎么办?

                比如这样:

                int a = 5;double b = 3.0;Add(a, b);

                请问这个模板是转化为double类型好呢,还是转化为int类型好呢?

                对编译器来说,这就是一个大问题了,如果转化错误了,编译器就要背黑锅。所以遇到这种情况,编译器不会为我们做决定,而是报错,必须由程序员指明要用哪一种类型的模板。

                比如使用强制类型转换:

                int a = 5;double b = 3.0;Add(a, (int)b);Add((double)a, b);

                上述代码,Add(a, (int)b);将b转化为了int,此时模板推演出int类型的函数;而Add((double)a, b);将a转化为了double类型,此时模板推演出double类型的参数。

                此外,我们还可以使用显式实例化的方式:

                显式实例化,就是在使用模板时,明确的告诉模板,要用什么类型。

                语法:

                函数名  (参数);

                比如:

                int a = 5;double b = 3.0;Add (a, b);Add (a, b);

                Add (a, b);此代码就是推演出int类型的函数;而Add (a, b);就是推演出double类型的函数。


                模板参数缺省

                在设置模板参数时,可以设置缺省值,在显式实例化时,对于没有指明的模板参数,会被推演为缺省值。

                看到以下模板:

                template void func(T1 a){T2 b = 5;cout T2 b = 5;cout return x + y;}int func(int x, int y){return x + y;}// 类内成员定义};public:stack(size_t capacity = 10):_pData(new T[capacity]),_size(0),_capacity(capacity){}private:T* _pData;size_t _size;size_t _capacity;};public:stack(size_t capacity = 10):_pData(new int[capacity]),_size(0),_capacity(capacity){}~stack();//声明private:int* _pData;size_t _size;size_t _capacity;};stack::~stack(){//函数体}//函数体}//函数体}public:private:T _arr[N];};return x 

上一篇:阿里云服务器怎么那么贵?

下一篇:烟花下载难题解析,揭秘无法顺利下载的真相!