zoukankan      html  css  js  c++  java
  • 泛型编程和模板

    泛型编程就是以独立于任何特定类型的方式编写代码,而模板是泛型编程的基础。

    1)定义函数模板(function template

    函数模板是一个独立于类型的函数,可以产生函数的特定类型版本。

    模板定义以关键字template开始,后接尖括号括住的模板形参表。

    模板形参可以是表示类型的类型形参(type parameter),也可以是表示常量表达式的非类型形参(nontype parameter)。下面程序中的T是类型形参。我会在另外的文章里分析类型形参和非类型形参。

    // implement strcmp-like generic compare function
    template <typename T>
    int compare(const T &v1, const T &v2)
    {
        if (v1 < v2) return -1;
        if (v2 < v1) return 1;
        return 0;
    }
    

    使用函数模板时,编译器会将模板实参绑定到模板形参。编译器将确定用什么类型代替每个类型形参,用什么值代替每个非类型形参,然后产生并编译(称为实例化)该版本的函数。

    下面的例子中,编译器用int代替T创建第一个版本,用string代替T创建第二个版本。

    // compiler instantiates int compare(const int&, const int&)
    cout << compare(1, 0) << endl;
    // compiler instantiates int compare(const string&, const string&)
    string s1 = “hi”, s2 = “world”;
    cout << compare(s1, s2) << endl;
    

    函数模板也可以声明为inline。

    // inline specifier follows template parameter list
    template <typename T> inline T min(const T&, const T&); 

    (2)定义类模板(class template

    在定义的类模板中,使用模板形参作为类型或值的占位符,在使用类时再提供具体的类型或值。

    template <typename Type> 
    class Queue
    {
    public:
        Queue();
        Type & front();
        const Type & front() const;
        void push(const Type &);
        void pop();
        bool empty() const;
    private:
        // …
    };
    

    与调用函数模板不同,使用类模板时,必须为模板形参显示指定实参。

    Queue<int> qi; // Queue that holds ints
    Queue<string> qs; // Queue that holds strings
    

    (3)模板类型形参

    类型形参由关键字class或typename后接说明符构成。在函数模板形参表中,二者含义相同。typename其实比class更直观,更清楚的指明后面的名字是一个类型名(包括内置类型),而class很容易让人联想到类声明或类定义。

    此外,在使用嵌套依赖类型(nested depended name)时,必须用到typename关键字

    在类的内部可以定义类型成员。如果要在函数模板内部使用这样的类型,必须显示告诉编译器这个名字是一个类型,否则编译器无法得知它是一个类型还是一个值。默认情况下,编译器假定这样的名字指定(静态)数据成员,而不是类型。所以下面这段程序,如果去掉typename关键字,将会出现编译错误。

    template <typename Parm, typename U>
    Parm fcn(Parm *array, U value)
    {
        typename Parm::size_type * p;
    }

    (4)非类型模板形参

    模板形参也可以是非类型形参,在使用时非类型形参由常量表达式代替。

    // initialize elements of an array to zero
    template <typename T, size_t N>
    void array_init(T (&parm)[N])
    {
        for (size_t i = 0; i != N; ++i)
            parm[i] = 0;
    }
    …
    int x[42];
    double y[10];
    array_init(x); // instantiates array_init(int (&)[42])
    array_init(y); // instantiates array_init(double (&)[10])

    (5)编写泛型程序

    模板代码需要对使用的类型做一些假设,比如上面的compare()要求类型T重载了“<”操作符。所以函数模板内部完成的操作就限制了可用于实例化该函数的类型。

    编写模板代码时,对实参类型的要求应尽可能少。比如compare()函数仅使用了“<”操作符,而没有使用“>”操作符。

  • 相关阅读:
    Confluence 6 PostgreSQL 设置准备
    Confluence 6 MySQL 问题解决
    Confluence 6 MySQL 测试你的数据库连接
    Confluence 6 MySQL 输入你的数据库细节
    Confluence 6 下载和安装 MySQL 驱动
    Confluence 6 MySQL 创建数据库和数据库用户
    Confluence 6 配置 MySQL 服务器
    Confluence 6 MySQL 数据库设置准备
    Confluence 6 SQL Server 问题解决
    Confluence 6 SQL Server 数据库驱动修改
  • 原文地址:https://www.cnblogs.com/zhanghu52030/p/6904946.html
Copyright © 2011-2022 走看看