当前位置:编程学习 > C/C++ >>

第16章 模板与泛型编程(6)

16.3 模板编译模型

当编译器看到模板定义的时候,它不立即产生代码。只有在看到用到模板时,如果调用了函数模板或定义了类模板的对象的时候,编译器才产生特定类型的模板实例。

应该将类定义和函数声明放在头文件中,而普通函数和类成员函数的定义放在源文件中。

模板则不同:要进行实例化,编译器必须能够访问定义模板的源代码。当调用函数模板或类模板的成员函数的时候,编译器需要函数的定义,需要那些通常放在源文件中的代码。

标准C++为编译模板代码定义了两种模型。在两种模型中,构造程序的方式很大程度上是相同的:类定义和函数声明放在头文件中,而函数定义和成员定义放在源文件中。两种模型的不同在于,编译器怎样使用来自源文件的定义。

1. 包含编译模型

在包含编译模型(inclusion compilation model)中,编译器必须看到用到的所有模板的定义。一般而言,可以通过声明函数模板或类模板的头文件中添加一条#include指示使定义可用,该#include引入了包含相关文件的源文件。

//Template1.h  
#ifndef TEMPLATE1_H  
#define TEMPLATE1_H  
template <class T> 
int compare(const T&, const T&); 
 
#include "Template1.cpp"  
#endif 
//Template1.h
#ifndef TEMPLATE1_H
#define TEMPLATE1_H
template <class T>
int compare(const T&, const T&);

#include "Template1.cpp"
#endif//Template1.cpp  
#include "stdafx.h"  
 
template <class T> 
int compare(const T &v1,const T &v2) 

    if(v1<v2) return -1; 
    else if(v2<v1) return 1; 
    else return 0; 

//Template1.cpp
#include "stdafx.h"

template <class T>
int compare(const T &v1,const T &v2)
{
 if(v1<v2) return -1;
 else if(v2<v1) return 1;
 else return 0;
}cout<<compare(100,200)<<endl; 
 cout<<compare(100,200)<<endl;2. 分别编译模型

在分别编译模型(separate compilation model)中,编译器会为我们跟踪相关的模板定义。但是,我们必须让编译器知道要记住给定的模板定义,可以使用export关键字(export keyword)来做这件事。

export关键字能够指明给定的定义可能会需要在其他文件中产生实例化。在一个程序中,一个模板只能定义为导出一次。编译器在需要产生这些实例化时计算出怎样定位模板定义。export关键字不必在模板声明中出现。

一般我们在函数模板的定义中指明函数模板是导出的,这是通过在关键字template之前包含export关键字而实现的。


函数模板的声明通常应放在头文件中,声明不必指定export。

通常,类声明必须放在头文件中,头文件中的类定义体不应该使用关键字export,如果头文件中使用了export,则该头文件中只能被程序中的一个源文件使用。

相反,应该在类的实现文件中使用export。

 摘自 xufei96的专栏
 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,