C++ 模板的编译 以及 类模板内部的实例化

在C++中,编译器在看到模板的定义的时候,并不立即产生代码,只有在看到用到模板时,比如调用了模板函数 或者 定义了类模板的

对象的时候,编译器才产生特定类型的代码。

一般而言,在调用函数的时候,只需要知道函数的声明即可;

在定义类的对象时,只需要知道类的定义,不需要成员函数的定义。

但是,这对于模板编译是不奏效的,模板要进行实例化,则必须能够访问定义模板的源代码,当调用函数模板以及类模板的成员函数

的时候,需要知道函数的定义。

标准C++对于模板的编译提供了两种策略:

相同之处:“将类定义以及函数声明放在头文件中,而函数定义以及成员函数的定义放在源文件中”。

不同之处:编译器怎样使用来自源文件的定义。

包含编译模型:

编译器必须看到用到的所有的模板的定义。

一般可以在声明类模板以及函数模板的头文件中添加include语句指示该定义可用。即:

#include “File.cc”    // File.cc是包含了相关函数实现的源文件

优点:保证了源文件与定义文件的分离。

缺点:在任何使用到该模板的源文件中,编译时,编译器都会为其实例化一份,也就意味着同一个函数模板可能有多份实例化,在链接的时候,编译器会选择一份实例化,扔掉其他的。

显然,这整个过程是很费时的。

分别编译模型:

编译器会跟踪相关模板的定义,因此我们必须事先告诉编译器,哪些模板是需要记住的。 使用 export关键字可以做到这一点。

每个模板只能使用export关键字一次!!

因此: 1   在函数模板的定义是指明该函数是可导出的; 2   在类的实现文件中使用export关键字,(如果在类定义的文件中使用,那么该头文件只能被某个源文件包含一次!!)。

即: export    template<typename T>   compare  (const T &, const T &) { …. }  // 在函数的实现体指明export

export    template<class T>    class    myClass; // 在类的实现文件中使用export

注:   虽然有点多余,但是还是说一下,类的定义文件以及实现文件,定义文件是指定义类的成员变量(即属性)的文件。实现文件是实现类的接口的文件。

值得注意的是:导出类模板的成员自动为导出的。

可以指定类模板的个别成员是可导出的,那么那些不可导出的成员必须遵循 包含编译模型,即定义必须放在定义类模板的文件中。

编译模板本身是很复杂的工作,但是这对用户而言是透明的,全部交给了编译器来承担,但是对于模板用户来说,仍然有一些难点。

在模板中,包含两种名字:依赖于模板形参的名字,以及不依赖于模板形参的名字。

对于模板的设计者来说,保证所有不依赖于模板形参的名字在模板本身的作用于中定义。

对于模板的使用者来说,保证与模板形参相关的函数、类型以及声明等可见。

类模板内部的实例化机制:

在下面的类模板中,有:

template<class T>

class Item

{

int val;

Item*next ; //在类的内部可以使用非实例化的版本,因为编译器默认在类的内部引用类的名字时,使用的是同一版本。

};

template<class T>

class Queue

{

public:

Queue & operator=(const Queue &); //同上

….

private:

Item<T> *head;  //此处必须类形参,因为编译器不会为类中使用的其他模板进行参数推断,因此需要自己指明。

Item<T>*tail;

};

C++ 模板的编译 以及 类模板内部的实例化

时间: 2024-10-27 04:43:04

C++ 模板的编译 以及 类模板内部的实例化的相关文章

C++—模板(2)类模板与其特化

我们以顺序表为例来说明,普通顺序表的定义如下: 1 typedef int DataType; 2 //typedef char DataType; 3 class SeqList 4 { 5 private : 6 DataType* _data ; 7 int _size ; 8 int _capacity ; 9 } ; 模板类也是模板, 必须以 关键字templ ate开头, 后接模板形参表. 模板类一般格式如下:template<class 形参名 1, class 形参名 2, .

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

 1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPushButton> #include <QLabel> template<class T> class run { public: T w; void show() { w.show(); } void settext() { w.setText("A"); }

C++学习之模板 (二) -----类模板

由于将函数和类模板放在一块篇幅较大,我们今天将其拆分为两篇博文. 上篇博文我们讨论了函数模板的简单应用,本篇我们继续讨论模板的另一板块--类模板. 1).作用:类模板类似于代码产生器,根据用户输入的类型不同,产生不同的class: 2).编译: a):检查模板class 的自身语法: b):根据用户指定的类型 如 vector<string>,去实例化一个模板类. 注意: 不是实例化所以的代码,而仅仅实例化用户调用的部分: 类模板:简单实现如下; 1 #include <iostream

第2章 类模板:2.1 类模板Stack的实现

Chapter 2: Class Templates 第2章 类模板 Similar to functions, classes can also be parameterized with one or more types. Container classes, which are used to manage elements of a certain type, are a typical example of this feature. By using class templates

C++ 之 类模板的分离式编译

模版编译篇 目录:1.对于C++中类模板的分离式编译的认识 2.具体的实例 1.对于C++中类模板的分离式编译的认识 为什么C++编译器不能支持对模板的分离式编译(博文链接) 主要内容:编译器编译的一般工作原理.对模版的分离式编译的特殊性(模版的特殊性) 链接: http://blog.csdn.net/pongba/article/details/19130 模版编译的特殊性 对程序进行编译时,对于函数调用,编译器只要求函数的原型在调用点是可见的,至于函数的定义是否存在不做检查(在对程序进行链

C++--第22课 - 类模板 - 下

第22课 - 类模板 - 下 1. 类模板的局部特化 类模板可以定义多个类型参数 #include <cstdlib> #include <iostream> using namespace std; template<typename T1, typename T2> class Test { public: void add(T1 a, T2 b) { cout<<(a + b)<<endl; } }; int main(int argc,

C++类模板

在上篇文章(C++函数模板)中,主要介绍了C++中函数模板,与函数相似,类也可以被一种或多种类型参数化.容器类就是一个具有这种特性的典型的例子, 本文地址:http://www.cnblogs.com/archimedes/p/cpp-class-template.html,转载请注明源地址. 以下通过设计一个类模板Stack的实现来说明: 类模板Stack的实现 #include<iostream> #include<vector> #include<stdexcept&g

函数模板与类模板

函数模板,顾名思义,是在生成函数时依照的模板. 有时,我们需要对不同的数据类型做同样的函数操作. 比如:分别对一个int类型数 和 一个double类型数求平方. 这时,虽然都是同样的求平方操作(函数体内代码一样),但是我们必须要编写两个不同的函数,因为处理int类型的函数的参数和返回值类型都应该是int,而处理double类型的函数的参数和返回值都应该是double. 如下:函数体内操作代码一样,设计为重载函数,用相同的函数名,但是参数类型和返回值类型却都不一样,函数需要定义两次. int S

18.2.2 简单的类模板

下面用前面的一个例子来说明,为数组定义一个类模板,该数组要对索引值进行边界检查,确保索引值是合法的.尽管标准库提供了数组模板的完整实现方式,但建立自己的数组模板有助于理解模板的工作原理.我们已经很清楚数组的工作原理了,因此下面集中讨论模板的特性.这也更容易使用第20章介绍的标准库中的 Array 模板. 数组模板只有一个类型参数,所以该模板的定义如下: template <typename T> class Array{ //definition of the template.. } Arr