C++模板

C++ 模板是一种对类型进行参数化的工具,使用模板的目的就是能够让程序员编写与类型无关的代码。
模板分为 函数模板类模板

函数模板的声明:

//template <typename type> ret-type func-name(parameter list)
//{
// 函数的主体
//}
template <typename T> T add(T t1, T t2)
{
    return t1 + t2;
}
int main()
{
    cout << add(1,2) << endl;//3
}

类模板的声明:

//template <class type> class class-name {
// ...
//}
template <typename T> class test_class 
{
public:
    T add_1(T t1, T t2)//类内实现
    {
        return t1 + t2;
    }
    T add_2(T t1, T t2);//类外实现
};
template<class T> T test_class<T>::add_2(T t1, T t2) {
    return t1 + t2;
}
int main()
{
    test_class<int> a;
    cout << a.add(1,2) << endl;//3
}

模板的形参:

模板形参有三种类型:类型参数非类型参数模板类型参数

1.类型参数

由class或者typename标记的参数,称为类型参数。类型参数是使用模板的主要目的, 参考上面代码。

那么class和typename,的关系和区别是什么呢,最后再说。

类型参数指定默认值

类模板的类型参数默认值和普通函数默认参数规则一致。

template<class T, typename M = double> void Show(T t, M m)
{
    cout << t << "-" << m << endl;
    return;
}
int main()
{
    Show(1, "test");//1-test
    Show<int, int>(1, 2.3);//1-2
    Show<int>(1, 2.3);//1-2.3
    Show(1, 2.3);//1-2.3
}
类型参数转换
template <typename T> T add(T t1, T t2)
{
    return t1 + t2;
}
int main()
{
    cout << add(1,2) << endl;//3
    cout << add<int>(1,2.3) << endl;//3
    cout << add<double>(1,2.3) << endl;//3.3
    cout << add(1,2.3) << endl;//编译报错-未找到匹配的重载函数
}

2.非类型参数

非类型参数是指内置类型参数。例如,定义如下模板:

template <typename T, int len> class test_class
{
public:
    int GetLen()
    {
        return sizeof(array);
    }
private:
    T array[len];
};
int main()
{
    test_class<int, 5> a;
    cout << a.GetLen() << endl;//20

    test_class<double, 8> b;
    cout << b.GetLen() << endl;//64
}

上述代码中int len就是非类型的模板参数。
使用非类型参数时,有以下几点需要注意。
(1)非类型参数只能是整型、字符型或枚举、指针、引用类型。
(2)调用非类型参数的实参必须是常量表达式,即必须能在编译时计算出结果。
(3)任何局部对象、局部变量的地址都不是常量表达式,不能用作非类型的实参,全局指针类型、全局变量也不是常量表达式,也不能用作非类型的实参。
(4)sizeof()表达式结果是一个常量表达式,可以用作非类型的实参。
(5)非类型参数一般不用于函数模板。

3.模板类型参数

模板类型参数就是模板的参数为另一个模板,声明格式如下所示:

//template <typename type_1, template<typename type_2, typename type_3> class type_class> 
//class class-name {
// ...
//}
template<typename T> class ExampleAdd {
private:
    T value;
public:
    void setValue(T val_1, T val_2) {
        value = val_1 + val_2;
    };

    T getValue() {
        return value;
    };
};

template<typename T> class ExampleRand {
private:
    T value;
public:
    void setValue(T val_1, T val_2) {
        if (0 == rand() % 2)
        {
            value = val_1;
        }
        else
        {
            value = val_2;
        }
    };

    T getValue() {
        return value;
    };
};

template <typename T, template<typename> class TC> class Example {
public:
    void printValue(T val_1, T val_2) {
        TC<T> instance;
        instance.setValue(val_1, val_2);
        std::cout << "Value: " << instance.getValue() << std::endl;
    }
};
int main()
{
    Example<int, ExampleAdd> Example_add;
    Example_add.printValue(42, 11);//Value: 53

    Example<std::string, ExampleRand> Example_rand;
    Example_rand.printValue("test", "val");//Value: val
}

class和typename的区别:
class可以用来定义类,也可用作模板参数类型,而typename只能用作参数类型。
因为最初发明模板时决定使用class以减少一个关键字,但后来发现还是不得不加上typename关键字,原因是模板类型参数的声明格式要求必须要有关键字class。
除此之外在模板中使用没有区别。

关于模板工作原理:
模板定义并不是真正的定义了一个函数或者类,而是编译器根据程序员缩写的模板和形参来自己写出一个对应版本的定义,这个过程叫做模板实例化。
编译器生成的版本通常被称为模板的实例。编译器为程序员生成对应版本的具体过程。类似宏替换。
模板类在没有调用之前是不会生成代码的。
由于编译器并不会直接编译模板本身,所以模板的定义通常放在头文件中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358

推荐阅读更多精彩内容

  • C++ 模板简介 一、模板 使用模板的目的就是能够让程序员编写与类型无关的代码。 模板是一种对类型进行参数化的工具...
    MinoyJet阅读 2,379评论 0 12
  • 我们想要定义多个函数,每个函数比较一种给定类型的值,可能定义多个重载函数。 这两个函数几乎是相同的,唯一不同就是参...
    Wangcy阅读 343评论 0 0
  • 一、概述 二、模板定义与使用  1. 函数模板的定义与使用 2. 类模板的定义与使用 三、typename 的特殊...
    从不中二的忧伤阅读 1,659评论 1 1
  • 模板 模板 Template是代码重用机制的重要工具 泛型技术:与数据类型无关的程序设计技术,是概念级的通用程序方...
    OuchDex阅读 98评论 0 0
  • C++模板 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成...
    A_MARK阅读 167评论 0 2