STL与模板

一、如何进行泛型编程
     C/C++ 是一种静态编程语言,必须需要把代码翻译成可执行的二进制可执行程序然后在运行,一旦编译好之后就不能再变了(数据类型也就必须确定下无法更改,因此要为每一种数据类型编写一份算法,工程量巨大)。

  C++提供了模板的编程方法来解决泛型编程的问题,它的解决思路是,程序员先编写好一份"套路"代码,然后在调用时编译器根据调用时的参数再为这种数据类型生成一份属于它的代码。

  C语言中也有类似的模板,比如快速排序。

 void qsort(void *base, size_t nmemb, size_t size,int(*compar)(const void *, const void *));

  以下是这个模板的应用:

 int intcmp(const void* p_1,const void* p_2)
    {
        int* p1 = p_1;
        int* p2 = p_2;
        if(*p1 == *p2) return 0;
        else(*p1 > *p2) return 1;
        else return -1;
    }
    int main()
    {
        int arr[10]={9,5,4,2,3,1,6,8,7,0};
        qsort(arr,10,sizeof(arr[0]),intcmp);
    }
    

注意点:这里的第4个参数的函数是需要我们自己提供的,也就是需要我们自己提供排序的规则。

二、C++中版本的语法

  

template <typename T,typename M ....>
    T max(T num1,T num2)
    {
        return num1 > num2 ?num1:num2;
    }

这里的T和M就是模板的参数类型,可以叫任何名字,只是约定俗成叫做T,它指的是函数调用时的任何类型的参数。

这个模板的使用,以下用冒泡排序举个例子:

#include <iostream>
#include <stdio.h>
#define swap(a,b) {typeof(a) t=a;a=b;b=t;}

using namespace std;
template <typename T>
void bubble_sort(T* arr,int size)
{
    for(int i=size -1;i>=0;i--)
    {
        for(int j=0;j<i;j++)
        {
            if(arr[j] > arr[j+1])
            {
                swap(arr[j],arr[j+1]);
            }
        }
    }
}
int main()
{
//    short arr[10] ={6,5,7,8,2,9,1,0,3,4};
//  char arr[10] ={‘6‘,‘5‘,‘7‘,‘8‘,‘2‘,‘9‘,‘1‘,‘0‘,‘3‘,‘4‘};
    char arr[10] ="absndkiro";
    for(int i =0;i<10;i++)
    {
        cout << arr[i] <<endl;
    }
}

三、函数模板的使用
    1、模板的实例化
        编译器不会把函数模板编译成一个实例,而是根据调用的参数,再进行实例化(进一步生成二进制指令)。
       
    2、使用模板时才实例化
        模板只有在调用时才会实例化,因此模板编译正确并不代表代码没有问题,很多错误会产生于调用时。
       
    3、二次编译
        第一次编译是检查模板的语法,第二次编译是根据调用参数把模板实例化出来再检查运算符是否支持这种类型。

四、函数模板的隐式推断
    a、使用函数模板时可以根据参数的类型来推断模板的参数。
   
    b、当函数模板不能通过函数调用时的参数来推断模板参数时,可以使用<类型,类型...> 来明确指定。
   
    c、函数的模板参数可以有默认值。
        1、默认值优先放在右边
        2、C++标准才支持  : -std=c++0x

六、类模板
    a、类模板的语法
    类模板的参数可以在类中当作类型使用,可以定义成员、返回值、参数等。
    template<class T,class A,class B...>
    class className
    {
        C c;
    public:
        T func(A a);
    }
    注意:typename也可以继续使用,但大多用class以示区别。

b、类模板的使用
    类模板必须要经过实例化才能使用,也是需要经过两次编译,第一次是把类模板编译成一个"套路",这个过程是为了检查语法,第二次是根据实例化参数,生成一个类,然后才能使用这个类创建对象。
   
    使用类模板实例化一个类:
    className<type1,type2...> a;

 以下举个例子,实现栈类模板:

#include <iostream>

using namespace std;

template<class T>
class Mystack
{
    struct Node
    {
        T data;
        Node* next;
        Node(T data):data(data),next(NULL)
        {}
    };
    Node* top;
public:
    Mystack(void)
    {
        top = NULL;
    }
    bool empty_stack(void)
    {
        return top == NULL;
    }
    void push_stack(T data)
    {
        Node* node = new Node(data);
        node->next =top;
        top = node;
        cout << data << endl;
    }
   bool pop_stack()
    {
        if(empty_stack()) return false;
        Node* temp = top;
        top = top->next;
        cout << temp->data << endl;
        delete temp;
        return true;
    }

};
int main()
{
    Mystack<int> stack;
    //Mystack<int>* stack = new Mystack<int>;
    for(int i=0;i<10;i++)
    {
        stack.push_stack(i);
    }
    for(int i=0;i<10;i++)
    {
        stack.pop_stack();
    }
}

c、类模板参数不支持隐式推断,必须显式实例化
   
    d、静态成员的定义
    template<class T> int MyStack<T>::num =10;
    静态成员必须是在类模板实例化之后才被真正定义处理,每一个实例化的类都有一份静态成员,这个实例化类创建出的对象共用一个静态成员。
    e、递归实例化
        Mystack<Mystack<int>> stack;
        尽量不要轻易使用

七、类模板的特化(重载)
    特化:指的是当类模板有特殊的类型无法处理时,可以为这种类型单独实例化出一个类,这种单独的实现叫做模板的特化。
    全类的特化:按照类的格式把类完整再实现一遍(重写一遍)。
    template<> class className<char*>
    {
       
    };
   
    成员特化:给指定的类型提供一个特殊的成员函数。
    template<> 返回值 className<char*>:: max(void)
    {
        ...
    }
    局部特化:可以让用户根据实例化时的参数来指定使用的类模板
   
    注意:同等程序的特化会引起二义性
   
八、类模板的参数
    1、类模板的参数可以有默认值。
        注意:使用类模板默认值时<>必须加上,可以空着,但不能不写。
    2、类模板后面的参数可以调用前面的参数。
   
    3、普通数值可以对类模板进行实例化,它必须以类似变量的形式存在。
    注意:只能是常量才能进行实例化。

原文地址:https://www.cnblogs.com/yyc954330712/p/9532887.html

时间: 2024-08-30 07:34:53

STL与模板的相关文章

STL 队列模板实现

C++ Prime确实有点难啊!看了好久都没弄清楚,一点点慢慢来. #include <iostream> #include <string> #include <cstdio> template <class Type> class Queue; //function template declaration must precede friend declaration in QueueItem template <class T> std:

STL:快速排序模板qsort(转载)

 qsort  用 法: void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *)); 各参数:1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小 4 指向函数的指针  int fcmp ( const void *a , const void *b ) { return *(int *)a - *(int *)b; } (注:当fcmp返回-1,则a会被排在b的前

C++ STL标准模板库

标准模板库 STL(StandardTemplate Library),即标准模板库,是一个具有工业强度的.高效的C++程序库.它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分.该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法,为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性.这种现象有些类似于Microsoft Visual C++中的MFC(MicrosoftFound

STL 标准模板库

STL(Standard Template Library,标准模板库), 组成: STL可分为容器(containers).迭代器(iterators).空间配置器(allocator).配接器(adapters).算法(algorithms).仿函数(functors)六个部分. 容器部分主要由头文件<vector>,<list>,<deque>,<set>,<map>,<stack>和<queue>组成.对于常用的一

STL(标准模板库)理论基础,容器,迭代器,算法

基本概念 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代器),容器和算法通过迭代器可以进行无缝地连接.几乎所有的代码都采 用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会.在C++标准中,STL被组织为下面的13

C++STL - 类模板

类的成员变量,成员函数,成员类型,以及基类中如果包含参数化的类型,那么该类就是一个类模板 1.定义 template<typename 类型形参1, typename 类型形参2,...> class 类模板名[:基类]{ 成员变量 成员函数 成员类型 }; 2.使用 类模板名<类型实参1,类型实参2,...> 对象; 类模板名<类型实参1,类型实参2,...> &引用 = 对象; 类模板名<类型实参1,类型实参2,...> *指针 = &对

C++STL - 函数模板

模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...> 返回类型 函数模板名(调用形参表){函数体} 在返回类型,调用形参表和函数体中,所需要类型的地方都可以引用模板形参表中类型形参 template<typename A,typenamen B,typename _C> A function(B arg){ _C var; ... } 2.使

C++ STL标准模板库(list)

//list的使用 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<list> using namespace std; /* 引用头文件 #include<list> list类本身是一个类模板 list链表中的迭代器list类模板的一个内部类 这个类实现了链表元素指针的功能 是一个线性链表结构,它的数据由若干个节点构成,每一个节点都包括一个 信息块(即实际存储的数据).一个前驱指针和一个后驱指针

C++ STL标准模板库(stack)

//stack的使用 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<stack> using namespace std; /* 引用头文件 #include<stack> stack类本身是一个类模板 stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,— —也就是说实现了一个先进后出(FILO)的数据结构. 1.empty() 堆栈为空则返回真 2.pop() 移除栈顶元素