当前位置:   article > 正文

c++系列七 —— STL编程之模板template_c++ stl template

c++ stl template

往期地址:

本期主题:
STL编程之模板template



0.前言——STL是什么?

STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库,它被容纳于C++标准程序库(C++ Standard Library)中。
从逻辑层次来看,在STL中体现了泛型化程序设计的思想(generic programming),引入了诸多新的名词,比如像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代子(iterator)等。与OOP(object-oriented programming)中的多态(polymorphism)一样,泛型也是一种软件的复用技术。

一次性引入了这么多名词,大家不用紧张,我们会用一个简单的例子来引出这些东西。

1.C++ 模板

模板是泛型编程的基础,简单理解泛型编程就像c语言中我们经常使用的函数指针

//模板函数的使用方法
template <typename type> ret-type func-name(param list)
{
}
  • 1
  • 2
  • 3
  • 4

看一个简单的例子,我们现在想实现一个函数,函数的作用是找出最大值,如果用传统的方法,当比较的数据是float型时,需要实现一个函数原型,比较的数据是int型时,又需要实现一个函数原型,这样十分的不灵活,因此我们可以使用模板编程的方法。

1.1 简单例子引出函数模板

include <iostream>

using namespace std;

/*
模板的使用例子:
1.创建一个模板方法用来实现不同参数类型的加法,例如add(int , int)以及add(float float);
2.如果用原来的方法,则每个类型都需要单独实现一个函数,效率太低,因此可考虑使用模板;
3.模板是泛型编程的基础,泛型编程指的是不指定具体类型的编程,与类型无关
4.模板编程的方法:
template <typename type>
ret-type func-name(param list)
*/
template <typename T>
T find_max(T& a, T& b)
{
    T temp;
    if (a < b)
        temp = b;
    else
        temp = a;
    return temp;
}

int main(void)
{
    int a = 1;
    int b = 2;

    cout << "the int max is " << find_max(a, b) << endl;

    float p1 = 8.7;
    float p2 = 3.3;
    cout << "the float max is " << find_max(p1, p2) << endl;

    return 0;
}

gary@ubuntu:~/workspaces/cpp_study/5.1.template$ ./app 
the int max is 2
the float max is 8.7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

1.2 定义类模板

就像我们定义函数模板一样,我们也可以定义类模板

template <typename type> class class-name {
}
  • 1
  • 2

例如我们现在定义一个模板类test,这个类中的两个私有成员都是模板,没有被实例化

/*
定义一个模板类,类中的方法也使用模板来进行实现
在最后调用的时候去确定template类到底代表着什么
*/
template <typename T> class test
{
private:
    T a;
    T b;
public:
    T find_max(void);
    void set_val(T, T);
};
//这句代码相对于是两个部分,前面的template <typename T>是代表对类型T的定义,告诉编译器T是一个模板;
//第二部分,void代表return type, test<T>代表test类以及T定义在test类中
template <typename T> void test<T>::set_val(T a, T b)  
{
    this->a = a;
    this->b = b;
}

template <typename T> T test<T>::find_max(void)
{
    T temp;
    if (a < b)
        temp = b;
    else
        temp = a;

    cout << "find_max is " << temp << endl;
    return temp;
}

int main(void)
{
    int a = 1;
    int b = 2;
    test<int> p1;   //在main中最后运行时,需要告诉编译器T的类代表啥;
    p1.set_val(1, 2);
    p1.find_max();

    test<float> p2;
    p2.set_val(1.2, 2.1);
    p2.find_max();
    return 0;
}
gary@ubuntu:~/workspaces/cpp_study/5.1.template$ ./app 
find_max is 2
find_max is 2.1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

2.模板友元函数

我们可以先回忆一下,当不使用模板时,友元函数是如何表达的
直接在类中定义时,用friend关键词表明友元函数

class xxx
{
private:
public:
	friend void func(const xxx& p);  //一般传入该类型的引用作为参数,这样才能访问该类型里的私有成员
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用模板友元函数的实际例子:

#include <iostream>
#include <string>

//该文件是使用模板类型的友元函数
using namespace std;
template <typename T> class People;
template <typename T> void print_age(const People<T>& p);
/*

*/
template <typename T> class People
{
private:
    T age;
public:
    People(){};
    People(T a):age(a){};
    
    friend void print_age<T>(const People<T>& p); //声明的函数名字中的这个T是必须的,如果不添加会报错:
/* 
3.1.5.template_friend.cpp:21:45: warning: friend declaration ‘void print_age(const People<T>&)’ declares a non-template function [-Wnon-template-friend]
     friend void print_age(const People<T>& p);
                                             ^
3.1.5.template_friend.cpp:21:45: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 
/tmp/ccWpihzK.o: In function `main':
 */

};

template <typename T> void print_age(const People<T>& p)
{
    cout << "age = " << p.age<< endl;
}

int main(void)
{
    People<int> a(10);
    print_age(a);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

总结:

  • 使用模板友元函数的时候,注意声明时与非模板的有差异,注意函数名后面的T
  • 定义时基本和模板函数一样

3.模板运算符重载

#include <iostream>
#include <string>

//该文件是定义一个使用运算符重载的模板
using namespace std;

/*

*/
template <typename T> class test
{
private:
    T age;
public:
    //T find_max(void);
    void print_test(void);
    test(){};
    test(T a):age(a){};
    //如果没有这个模板T的话,运算符重载的定义应该是
    //test operator+(test  &) 有了T之后变成了
    test<T> operator+(test<T> &other);


};
//template <typename T>告诉编译器T是一个变量
//第一个test<T>是返回值类型,第二个test<T>是代表属于这个类
template <typename T> test<T> test<T>::operator+(test<T> &other) 
{
    test<T> tmp;
    tmp.age = this->age + other.age;
    return tmp;
}

template <typename T> void test<T>::print_test(void)
{
    cout << "age = " << this->age << endl;
}

int main(void)
{
    test<int> a(13);
    test<int> b(12);
    test<int> c(0);
    c=a+b;
    c.print_test();
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/1008665
推荐阅读
相关标签
  

闽ICP备14008679号