【C++学习历程8】函数模板和类模板

什么是函数模板
所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。
凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。

定义:
template <类型形式参数表>
例如:template <typename T>

函数模板声明:
类型 函数名 (形式参数表)

函数模板和普通函数的区别:函数模板不允许自动类型转化;普通函数能够进行自动类型转换。
函数模板和普通函数在一起调用规则:
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
4 可以通过空模板实参列表的语法限定编译器只通过模板匹配

函数模板机制
一个函数模板就可以代表一系列的函数,很是神奇,那么,它的原理到底是什么呢?编译器并不是把函数模板处理成能够处理任意类的函数。编译器真正的做法是:从函数模板通过具体类型产生不同的函数,对函数模板进行两次编译:在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。例如:
template
T max(T a, T b)
{
return a > b? a : b;
}
max(10,20);
两次编译后,实际上相当于:
int max(int a, int b)
{
return a > b? a : b;
}
max(10,20);
编译器代替我们实现了这个函数。

类模板

template <typename T>
class A
{
public:
    A(T a)
    {
        this->a = a;
    }

    void print ()
    {
        cout << "a = " << a << endl;
    }
private:
    T a;
};


// 类模板对象做函数参数传递的时候
// 1、写一个具体的 模板类 对象
void myPrint(A<int>  &a)
{
    a.print();
}

void myPrint(A<double> &a)
{
    a.print();
}

// 2、使用函数模板
template <typename T>
void  printA(A &a)
{
    a.print();
}

int main()
{
    // 函数模板可以隐式调用, 但是 类模板不能隐式调用,必须说明模板类型
    A<int> a(10);   
    A<double> d(1.2);

    myPrint(a);
    myPrint(d);

    printA(a);
    printA(d);

    return 0;
}

2、类模板的派生
1)派生普通类(具体的类)

class B : public A<int>
{
public:
    B(int a,  int b): A(a)
    {

    }
private:
    int b;
};

2)派生类模板(非具体的类)

template 
class C:public A
{
public:
    C(int a, T c):A(a)
    {

    }
private:
    T c;
};

3、类模板中的static关键字
*从类模板实例化的每个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员
*和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围定义和初始化
*每个模板类有自己的类模板的static数据成员副本

小结:
1模板是C++类型参数化的多态工具。C++提供函数模板和类模板。
2 模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。
3同一个类属参数可以用于多个模板。
4 类属参数可用于函数的参数类型、返回类型和声明函数中的变量。
5模板由编译器根据实际数据类型实例化,生成可执行代码。实例化的函数模板称为模板函数;实例化 的类模板称为模板类。
6 函数模板可以用多种方式重载。
7类模板可以在类层次中使用 。

你可能感兴趣的:(学习记录)