谈一谈C++ template/C++ 模板

Posted xioacd99

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谈一谈C++ template/C++ 模板相关的知识,希望对你有一定的参考价值。

这里劝退一波 Qt Ui,仅仅是 Ui,不是 Qt 哈

选择 Qt 一时爽, Ui 开发火葬场。

忙活两个小时,解决的只是一个非常小的窗口效果,接下来考验你的眼力的时间到了

你找到了上面两幅图的不同了吗?

文章目录

1 为什么要使用模板

也许平常写 C++ 的时候我们不用模板也能 6 得飞起,那为什么还会要产生模板的需求呢?

以下面的例子为例,如果我有了模板,我就可以生产同一类型的多个表情包


但是没有模板的你只能使用最原本的熊猫人,在斗图大战中败北,含恨而归


形象吧,接下来我们来谈一谈什么时候该使用模板,以及模板的语法和分类。

2 究竟我是否该使用模板

是否要用模板,我们可以借鉴开发时的 RunOfThree 原则

RunOfThree原则

  1. 第一次用的时候写个“特例”
  2. 第二次用的时候copy第一次的代码,
  3. 第三次用的时候就得写一个通用的,当然,为了达到通用性,你要做的不仅仅是使用模板。

3 C++ 模板语法与分类

模板下面又分为函数模板类模板模板类等等,这里我们简单地谈谈前面三种

3.1 函数模板

语法

template <class T1,class T2,...,>
返回类型 函数名(形参表)
    statement;

例子

template <class T>
// equal to template <typename T>
T max(const T& a, const T& b) 
    return a > b ? a : b;

说明

  1. template是C++中用来声明模板的keyword,class和typename是模板形参的声明,两者的差别见:difference of keywords typename and class in templates
  2. 并不是写了函数模板就可以自动处理所有类型的数据了,比如上面的max函数。如果你相对两个自定义类型对象使用,你还得自己重载运算符>。

3.2 类模板和模板类

虽然我们说模版类就是类模版实例化之后的类,但其实there is no such thing as a “template class,” there is only a “class template.”,见what is the difference between a template class and a class template

语法

template <class T>
class TestClass
	function;
    member;
;

例子

template <class T>
class TestClass
public:
    void testFunction();
private:
	T m_value; // 用个m_前缀方便将类成员变量和普通的区分开member 
    		   // 但是不要两种命名方法混用,就像这样
;

注:

  1. 类模板中的成员变量同样可以是int、double这种,可以类比到函数

  2. 类外定义成员函数需要多加一些东西

template <class T>
void TestClass<T>:: testFunction()
	statement;

使用:我们所说的使用类模板就是利用模板生成一个具体的类,就像用摸具爸爸做出摸具儿子一样,然后我们再用摸具儿子就可以创建具体的对象来使用了。

3.3 模板的覆盖与特化

首先,来一个非常形象的解释


模板的覆盖和特化就像程序员给的小红伞,可以让特化后的类无视原来模板的规定,自行对相关情况进行处理。

3.3.1 模板的覆盖

和前面重载一样,如果类中出现有一个函数和模板中的参数原型一致,那么模板就会被覆盖(specifial first)

3.3.2 模板的特化

什么时候使用:写的模板能够处理大多数情况,数据只是小部分特例,重新写一个不划算。

分类

  1. 函数模板特化
// 原模板
template <typename T>
bool isZero(const T& a)
    return a.value == 0;


// 特化
template <>
bool isZero<int>(const int& a)
    return a == 0;

没有原模板就别谈特化了

  1. 类部分特化
template <typename T1,typename T2>
class TestClass
 ...
;

// 这里只需要写为进行特化的模板类型
template <typename T>
class SpecificalClass<T,int> 
...  
;
  1. 类全特化
template <typename T1,typename T2>
class TestClass
	...
;

template <>
class SpecificalClass<int,int> 
	...  
;

3.4 类模板与友元

3.4.1 按照定义的位置来分

  1. 封闭型
  template <typename T>
  class TestClass
      // 函数体定义在模板体类,可以访问A任意实例的任意成员
  	friend void testFunction()
      	statement;
  	
  ;
  1. 开放型
  template <typename T>
  class TestClass
      template <typename T1>
      friend void testFunction<T1>();
  ;
  
  // 函数体定义在模板类外,友元可以访问A任意实例的任意成员
  
  template <typename T>
  void testFunction
  	statement;
  
  1. 特例型
   template <typename T>
   class TestClass
   	// 此时只有和类模板具有相同模板形参的友元函数才算是TestClass的友元
   	friend void testFunction<T>();
   ;

3.4.2 按照约束来分

  1. 模板类的非模板友元函数

    1. 不用模板的成员变量

      template <typename T>
      class TestClass
          // 和普通的友元函数没什么差别
      	friend void testFunction()
      		statement;
          
      ;
      
    2. 用~

      template <typename T>
      class TestClass
          // 必须为每一个需要使用到的类型给出一个定义,属于overload
      	friend void testFunction(TestClass<T>& obj);
      ;
      
      // 假设我的代码中只用到了int和double
      void testFunction(TestClas<int>& obj)
      	statement;
      
      
      void testFunction(TestClas<double>& obj)
      	statement;
      
      
    3. 模板类的约束类友元函数

      每一个类的具体化都要有一个友元定义,有点像1.2,不过你需要在模板类前先声明友元函数

      // 以这种形式
      template<typename T>void testFunction();
      
    4. 模板类的非约束友元函数

      有点像1.3

q imok aos hibu k aoz hex ie

以上是关于谈一谈C++ template/C++ 模板的主要内容,如果未能解决你的问题,请参考以下文章

谈一谈.net析构函数对垃圾回收的影响

C++模板类模板的全部特例化和局部特例化(偏特化-partial specialization)

C++ Primer 5th笔记(chap 16 模板和泛型编程)类模板部分特例化

谈一谈购物车

C++ Primer 5th笔记(chap 16 模板和泛型编程)类模板特例化

谈一谈Elasticsearch的集群部署