C++中的泛型编程有函数模板与类模板

一、函数模板

        函数模板是一种特殊的函数,可以使用不同的类型进行调用,对于功能相同的函数,不需要重复编写代码,并且函数模板与普通函数看起来很类似,区别就是类型可以被参数化,在使用函数模板时有两种方式:

    1、自动类型推到调用 Swap(a, b)

    2、具体类型显示调用 Swap(a, b)

例子:

#include 
using namespace std;


template 
void Swap(T& a, T& b)
{
    T tmp = a;
    a = b;
    b = tmp;
}

void main()
{
    int a = 10;
    int b = 20;
    Swap(a, b); //自动推到调用
    //Swap(a, b);//显示指定调用
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    float c = 12.3;
    float d = 23.4;
    //Swap(c, d); //自动推到调用
    Swap(c, d); //显示指定调用
    cout << "c = " << c << endl;
    cout << "d = " << d << endl;
    system("pause");
}

对于函数模板中使用的类型不同,编译器会产生不同的函数;

编译器会对函数模板进行两次编译:

        1、第一次是对函数模板本身进行编译,包括语法检查等;

        2、第二次是对参数替换后的代码进行编译,这就相当于编译普通函数一样,进行类型规则检查等;

        注意事项:函数模板是不允许隐式类型转换的,调用时类型必须严格匹配;

函数模板还可以定义任意多个不同的类型参数,但是对于多参数函数模板:

    1、编译器是无法自动推导返回值类型的

    2、可以从左向右部分指定类型参数

例子:

#include 
using namespace std;

template 
T1 add(T2 a, T3 b)
{
    T1 ret;
    ret = static_cast(a + b);
    return ret;
}

void main()
{
    int c = 12;
    float d = 23.4;
    //cout << add(c, d) << endl; //error,无法自动推导函数返回值
    cout << add (c, d) << endl; //返回值在第一个类型参数中指定
    cout << add (c, d) << endl;
    system("pause");
}

输出:
    35.4
    35

        注意事项:定义了多类型参数的函数模板,调用时需要注意的是函数返回值需要在第一个参数类型中显示指定,后边的类型可自动推导或显示指定;

函数模板跟普通函数一样,也可以被重载:

    1、C++编译器优先考虑普通函数

    2、如果函数模板可以产生一个更好的匹配,那么就选择函数模板

    3、也可以通过空模板实参列表<>限定编译器只匹配函数模板

例子:

#include 
using namespace std;


template 
void fun(T a)
{
    cout << "void fun(T1 a)" << endl;
}

template 
void fun(T1 a, T2 b)
{
    cout << "void fun(T1 a, T2 b)" << endl;
}

void fun(int a, float b)
{
    cout << "void fun(int a, float b)" << endl;
}

void main()
{
    int a = 0;
    float b = 0.0;
    fun(a);
    fun(a, b); //普通函数void fun(int a, float b)已经能完美匹配,于是调用普通函数
    fun(b, a); //这个调用,函数模板有更好的匹配,于是调用函数模板
    fun<>(a, b); //限定只使用函数模板
    system("pause");
}

        编译器会优先去调用普通函数,但是当函数模板有更好的匹配时或使用限定符<>时,编译器就会去匹配函数模板。

函数模板的作用:

    - 函数模板是泛型编程在C++中的应用方式之一

    - 函数模板能够根据实参对参数类型进行推导

    - 函数模板支持显示的指定参数类型

    - 函数模板是C++中重要的代码复用方式

    - 函数模板通过具体类型产生不同的函数

    - 函数模板可以定义任意多个不同的类型参数

    - 函数模板中的返回值类型必须显示指定

    - 函数模板可以像普通函数一样重载

二、类模板:

        将模板的思想应用于类,我们就可以只关注类的功能实现,不需要关注具体数据元素的类型,这种思想非常适用于编写数据结构相关的代码,比如数组类、线性表、栈和堆等,只需要实现他们的逻辑功能,不必关注具体的数据类型。

         C++中的类模板与函数模板一样,都是使用template 这样的格式来声明使用的是类模板。

template 
class test
{
    private:
    T m_value;
    public:

    test(T value)
    {
        m_value = value;
    }

    T get()
    {
        return m_value;
    }
}

        其中的T代表任意的类型,可以出现在类模板中的任意地方,与函数模板不同的是,使用类模板时必须显示的指定数据类型,编译器无法自动推导。

编译器对类模板的处理与对函数模板的处理相同:

    - 从类模板通过具体类型产生不同的类

    - 在声明的地方对类模板代码本身进行编译

    - 在使用的地方对参数替换后的代码进行编译

例子:

#include 
#include 
using namespace std;

template 
class test
{
        private:
        T m_value;

        public:
        test(T value)
        {
            m_value = value;
        }

        T get()
        {
            return m_value;
        }
}

void main()
{
    //test t(12.3); //error, 不能自动推导类型
    test t1(12); //显示指定类型为int
    test t2("hello C++"); //显示指定类型为string
    cout << t1.get() << endl;
    cout << t2.get() << endl;
    system("pause");

}

输出:
    12
    hello C++

我们在定义类模板时,一般的规则是

    - 将类模板声明和定义必须在头文件中

    - 类模板里边的成员函数,必须要同一个文件中实现

    - 类模板外部定义的成员函数需要加上template 类似的声明

将上边的test类模板实现在test.h头文件中,并将成员函数在外边实现:

#ifndef __TEST_H__
#define __TEST_H__
template 

class test
{
    private:
    T m_value;

    public:
    test(T value)
    {
        m_value = value;
    }

    T get();
};

template  //类外实现的成员函数需要加上类似的模板声明
T test::get()
{
    return m_value;
}

#endif //__TEST_H__

与函数模板一样,类模板也可以定义多个参数,例如:

template 

class test
{
    private:
    T1 m_value1;
    T2 m_value2;

    public:
    test(T1 value1, T2 value2)
    {
        m_value1 = value1;
        m_value2 = value2;
    }
}

总结:

    - C++类模板与函数模板一样,以相同的方式处理不同的类型,达到代码复用

    - 类模板非常适用于编写数据结构相关的代码

    - C++类模板在使用时只能显示指定类型

三、函数模板和类模板的区别 :

        1、函数模板允许隐式调用和显式调用而类模板只能显示调用。

        2、名词区别:

类模板与模板类区别:

类模板:

        类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。

例如:

template   class Vector {  … }

模板类:

        模板类的重点是类。表示的是由一个模板生成而来的类。

例如:

        Vector 、Vector 、……全是模板类。

函数模板与模板函数区别:

函数模板:

函数模板的重点是模板。表示的是一个模板,专门用来生产函数。

template   void  fun(T   a) { … }

模板函数:

模板函数的重点是函数。表示的是由一个模板生成而来的函数。

显式(explicitly)的模板函数:

        fun 、fun 、fun ...

隐式(implicitly)的模板函数:

        fun(6); //隐式生成fun

        fun(8.9); //隐式生成fun

        fun(‘a’);//隐式生成fu

你可能感兴趣的:(c++,linux环境,编译问题,算法,c++,开发语言)