调试环境 win10+vs2015

模板是c++中泛型编程的基础,一个模板就是一创建类或函数的蓝图或者说公式。(c++ primer)

其实模板对于我们生活来说是十分常见的,在编程这里也不例外。
对于编程的初学者来说,多写一点代码,可以增加代码熟练度,但是对于工程来说,那就是浪费时间。
所以c++提供了模板这个机制。

如何编写一个通用的加法函数

  1. 使用函数重载,针对每个所需相同行为的不同类型重新实现它
    缺点:
    只要有新类型出现,就要重新添加对应函数
    出类型外,所有函数的函数体都相同,代码重复率不高
    如果函数只是返回值类型不同,函数重载不能解决
    一个方法有问题,所有方法都有问题,不好维护
  2. 使用公共基类,将通用代码放在公共的基础类里面
    缺点:
    借助公共基类来编写通用代码,将失去类型检查的优点
    对于以后实现的许多类,都必须继承自某个特定的基类,代码维护更加困难
  3. 使用特殊的预处理程序
    缺点
    不是函数,不进行参数类型检测,安全性不高
  4. 使用模板

声明模板
函数模板:代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

//模板函数以关键字typelate开始,后跟一个模板参数列表,里面是模板参数的列表,以逗号分隔,用<>括起
template<typename T>//typename也可以使用class来代替,但是最好用typename,一些较早的编译器可能不识别class
T fun(T t1,T t2){}//定义了一个模板函数,如果函数函数需要定义成内联函数,inline关键字必须房子啊模板形参表之后,返回值之前,不能放在template之前

注意:
一个模板函数之前必须有与之匹配的template,也就是说一个template关键字只能修饰一个模板函数
例如

//错误 
template<typename T>
T Max(const T& a,const T& b) {
    return (a>b) ? a : b;
}
T Min(const T& a, const T& b) {     //
    return (a<b) ? a : b;           // 编译器会报错
}                                   //

//正确
template<typename T>
T Max(const T& a,const T& b) {
    return (a>b) ? a : b;
}
template<typename T>
T Min(const T& a, const T& b) {
    return (a<b) ? a : b;
}

编译模板
模板在c++编译器里面会编译两次
第一次:实例化之前,检查语法错误
第二次:实例化期间,检查模板代码,查看是否所有的调用都有效
例:

template<typename T>
T Add(const T& a, const T& b) {
    return a + b;
}

class Date {

};

int main() {
    Date d1, d2;
    Add(d1, d2);//这里vs是不是在底下打红线提示报错,但是编译的时候会报错,因为Date类没有定义加法运算
    return 0;
}

形参推演:从函数实参确定模板形参类型和值的过程,多个类型形参的实参必须完全匹配

类型形参转换:一般不会转换实参已匹配已有的实例化,相反会产生新的实例
编译器只会执行两种转换

  1. const转换:接收const引用或者const指针的函数可以分别用非const对象的引用或者指针来调用
  2. 数组或函数到指针的转换:如果模板形参不是引用类型,则对数组或函数类型的实参应用常规指针转换。数组实参将当做指向其第一个元素的指针,函数实参当做指向函数类型的指针。

模板参数
函数模板有两种:模板参数和调用参数
模板参数分为类型形参和非类型形参
模板形参名字只能在模板形参之后到模板声明或定义的末尾之间使用,遵循名字屏蔽规则。

模板匹配问题
模板能否匹配对于初学者来说很是困难,尤其是在模板里面加上了const
这里讨论以下一些情况

template <typename T>
T Add(const T& left, const T& right) {
    return left + right;
}

int main() {
    Add(1, 2);//隐式调用,实例化一个Add<int,int>的函数
    Add(1, '2');//错误,类型不一样,模板函数不会进行隐式转换,函数重载会
    Add(1, int('2'));//正常调用,使用强制转换将其装换成ing
    Add<int>(1, '2');//显式调用
    return 0;
}
template<typename T>
T Add(const T& left, const T& right) {
    return left + right;
}
class Date {
public:
    错误格式
    Date& operator+(const Date& date) {
        _date += date._date;    //这里不能使用模板函数,模板函数第一个参数时const
        return *this;
    }

    Date operator+(const Date& date)const {
        Date d;
        d._date = date._date+_date;    //模板函数可以调用
        return d;
    }
    int _date;
};
int main() {
    Date d1, d2;
    d1._date = 1;
    d2._date = 2;
    d1 = Add(d1,d2);
    return 0;
}

模板函数特例化

template <typename T>
T Add(const T& left, const T& right) {
    return left + right;
}
class Date {
public:
    Date operator+(const Date& date)const {
        Date d;
        d._date = date._date+_date;
        return d;
    }
    int _date;
};
int main() {
    Date d1, d2;
    d1._date = 1;
    d2._date = 2;
    Add(d1,d2);

更多推荐

c++模板函数