[Cpp] C++ 群体类和群体数据的组织

一 、模板的实例化机制

1、模板和模板实例关系的辨析

类模板本身不是类,不能表示一种数据类型,只有模板的实例才能当成类来使用(书写为带参数的类的模板)

Array 是一个模板类,我们想对其中的元素颠倒过来,像下面声明函数原型是不行的 :

1
void reverse(Array &arr);

此时的 Array 并不是一个有效的数据类型,而是一个模板;

如果想对一个 int 型的 Array 进行操作的话,我们只需要给予其参数,如下

1
void reverse(Array<int> &arr);

但是这样并不是一个长久之计,我们可以将其写成一个函数模板

1
template<class T>void reverse(Array<T> &arr);

总之,使用模板的时候使用,一定要对其进行参数赋值的操作,既是<?>中的类型一定要给予
而且需要注意的是,同一个类根据不同参数生成的不同的模板实例是完全无关的类型;

编译器不会对函数模板或者类模板生成目标代码

如果编译器可以根据参数推断出模板的类型并能生成模板实例的话,隐式调用模板还是可以的;不然的话就只能显式的调用了

2、隐含实例化

编译器根据函数模板或者根据类模板生成实例的过程叫做模板的实例化
· 对一个类进行实例化,被实例化的只有其中成员的声明被实例化了
· 只有在调用相关模板的时候,才会对其进行实例化(也就是说,调用那个模板就会实例化那个模板——既是按需进行)

3、多文件结构中模板的组织

因为模板的按需实例化机制

函数模板,类模板成员函数,类模板静态数据成员只能将声明放在头文件中
举一个简单的例子:
· 比如将 Array 模板中的成员函数的定义全部放到一个新建的 Array.cpp 中去,这个时候,其他的cpp文件如果需要使用到Array模板,虽然可以对Array模板实例化,但是却不能够实例化其中的成员函数

因为一般的编译系统对每一个源文件的编译是分别进行的,所以要在其他的cpp文件中访问到实例化的模板成员函数时,链接时是会出错的


细节
函数模板和类模板的成员函数都放在头文件中,是不是和内联函数相同呢?
其实不是的,函数模板和和类模板的成员函数可以是内联函数,也可以不是
如果是的话,就要是使用到inline关键字,或者将其写在类的定义中


注意 : 使用不同的参数实例化了相同头文件中的同一个模板,会在两个源文件的目标文件中生成两份相同的代码,链接时可能会出错,这点不用担心,因为编译器帮我们做了检测的工作,当然如果要去深究的话,自己去寻找相关的资料吧;

4、显示实例化

为了将让函数模板,类模板的成员函数和静态数据成员的定义放在源文件中

语法格式:

1
template 实例化目标的声明;

对类模板进行显式实例化时,类模板的成员函数和静态数据成员的定义也会被实例化