雨落无声

C++ 中 Template 的使用
前言今天教授讲得很快,很多同学可能都没搞清 Template 到底是个啥东西。。我就慢慢写一下吧。有问题的地方还请...
扫描右侧二维码阅读全文
15
2018/02

C++ 中 Template 的使用

前言

今天教授讲得很快,很多同学可能都没搞清 Template 到底是个啥东西。。我就慢慢写一下吧。有问题的地方还请大佬们纠正。

简述

Template 顾名思义,就是模版。我们在写一个正常的函数的时候,都需要指定这个函数的返回值 return 类型,参数类型等。然后我们再写具体的函数内容部分。

举例:

#include <iostream>

int func1(int a, int b){
    return a * b;
}
    
float func2(float a, float b){
    return a * b;
}
    
int main(){
    std::cout << func1(9, 9)<< std::endl;
    std::cout << func2(9.0, 9.0)<< std::endl;   
    return 0;
}

func1 和 func2 这两个函数都是计算两个数的乘积,唯一的区别就是

  • func1 接受两个 int 类型的整数,返回 int 类型的整数。

  • func2 接受两个 float 类型的小数,返回 float 类型的小数。

我们只想实现一个乘法,却需要分别针对小数和整数写一种方法,但是他们的实现过程都是一样的。如果我们想要对 long 类型,double 类型使用同一种方法,是不是需要写很多次完全一样的函数主体内容呢?

于是 Template 就出现了,针对不同类型的数据,使用同一种思路。就像是一种模板一样,可以套用多种数据。

举例:

#include <iostream>
template<class T>

T func3(T a, T b){
   return a * b;
}

int main() {
    std::cout << func3(9, 9) << std::endl;
    std::cout << func3(9.0, 9.0) << std::endl;
    return 0;
}

模板类

区别:定义方式

不仅仅是函数可以套用模板,类(Class)也可以套用模板。

先看一个最基本的类的:

// Class Point2D without using Template
    
#include <iostream>
    
class Point2D{
    
public:
    Point2D(int a, int b){
        x = a;
        y = b;
    }
    
    int get_x(){  return x;  }
    
    int get_y(){  return y;  }
    
    void set(int a, int b);
    
private: 
    int x;
    int y;
};
    
int main(){
    int a = 5;
    int b = 5;
    Point2D p(a,b);
    std::cout << p.get_x() << std::endl;
    std::cout << p.get_y() << std::endl;
}

这个 Point2D 类应该很熟悉,一下子就能看懂。但是现在问题来了,我们在这个类里面写的都是 int 类型的 xy 坐标值,如果我们的 x 和 y坐标是小数该怎么办?是不是需要重新洗一个类?

Template 可以很完美的解决这个问题,使用 Template 重写后:

// Class Point2D with Template
    
#include <iostream>

template<class T> class Point2D {
    
public:
    Point2D(T a, T b){
        x = a;
        y = b;
}
    
    T get_x(){  return x;  }
    T get_y(){  return y;  }
    
    void set(T a, T b);
    
private: 
    T x;
    T y;
};
    
int main(){
    
   /* Point2D of int */
   int a = 5;
   int b = 5;
   Point2D<int> p1(a,b);
   std::cout << p1.get_x() << std::endl;
   std::cout << p1.get_y() << std::endl;
    
   /* Point2D of float */
   float c = 8.0;
   float d = 8.0;
   Point2D<float> p2(c,d);
   std::cout << p2.get_x() << std::endl;
   std::cout << p2.get_y() << std::endl;
    
   return 0;
}

对比一下两段 class 的代码,似乎就是把所有的 int 都换成了 T 而已,但是却能适用于非常多的类型。主函数里只要填写 T 的具体类型,这个类的操作就会变成这个类型的。

区别:使用方式

主函数 int main() 里面创建这个类的实例的时候我们对比一下。

int main()
{
    Point2D p1(5,5);                //不使用Template的时候       
    
    Point2D<int> p2(8,8);           //使用Template的时候需要用 <> 指定类型。
}

简单的来说就是使用 Template 之后,你需要在主函数里实例化一个对象的时候,需要用 <> 加上类型,比如 int,float 之类的,让这个类使用你指定的类型。

区别:Implement方式

不使用 Template 的时候:

//Point2D.cpp

void Point2D::set(int a, int b){
    x = a;
    y = b;
}

使用 Template 的时候:

//Point2D.cpp

template<class T> void Point2D<T>::set(T a, T b){
    x = a;
    y = b;
}

区别就在于,Implement 一个使用 Template 的类的时候,要在最前面加上template<class T>在类名称后面加上<T>

其他知识

今天还讲了些其他的相关知识,简单列举下:

Typedef

typedef这个命令就是用来偷懒,简写类型的。比如unsigned int要打的字要多,我们就用 typedef来简化:

    typedef unsigned int mytype;
    
    unsigned int a = 10;
    
    mytype b = 20;

就相当于把 mytype 当作 unsigned int 来使用了,省的打那么多字。

this

this 是一个指针(Pointer),它始终指向这个实例本身。

PDF中的用途:

  1. 在类里面访问实例自己的方法或者变量时可以使用,强调这个变量是自己的。

  2. 用于比较某个实例是否是自己。

第一点:当函数传入的参数名和自己成员变量名一样的时候:

class MyClass{
    
public:
    MyClass (int a){
        (*this).a = a;     //The same as this -> a = a;
    }
    
private:
    int a;
    
};
int main(){
    MyClass h(1);
}
    
/* 为什么不用 *this.a = a
因为 . 运算符的优先级很高,所以它的执行方式是这样的:*(this.a) = a,因为 this 是一个指针地址,没有 .a 这个成员变量,只有 this 的内容,即 *this 才可以使用 .a 。所以我们加括号来确保 * 符号先运行,即 (*this).a = a; 为了简写,我们直接使用 this -> a 就可以代替了。
*/

第二点:检查另一个实例是否为自己的时候:

#include <iostream>
    
class MyClass{    
public:
    MyClass (int num){
        a = num;
    }
        
bool operator==(const MyClass & other) const{
    if(this == &other){
        return true; // Because other is my self
    }
    else{
        return a == other.a;
    }            
}
    
private:
    int a;    
};
    
int main(){
    MyClass h(1);
    MyClass j(1);
    std::cout << (h == h) << std::endl;
    std::cout << (h == j) << std::endl;
    
    return 0;
}
Last modification:April 19th, 2018 at 01:38 am
If you think my article is useful to you, please feel free to appreciate

One comment

  1. 曹老师

    %%%

Leave a Comment