模板的声明、定义分为两种。
1 将模板的声明和定义都放在头文件中,在主程序的文件中包含此头文件即可
2 将模板的声明和定义分开编写。
在《C++ primer》教材中,将模板的声明和定义分别放在头文件(.h)和(.cpp)中的模板编译模型分为两种,一种是包含编译模型(inclusion compilation model),另一种是分别编译模型(separate compilation model)。其中,包含编译模型,所有编译器都支持,但是分别编译模型,大部分编译器(包括VS2017)却不支持。
2.1 包含编译模型
以下列例子为例:
//头文件 head.h
#pragma once
#ifndef TEMPLATE_DEMO_01
#define TEMPLATE_DEMO_01
template<typename TT> void gg(const TT &t);
template<typename TT> void ggg(const TT &t);
#include"head.cpp" //注意这里要添加函数模板定义的源文件的名字,head.cpp
#endif // !1
对应的模板函数的定义在对应的源文件中:
//函数模板的定义 head.cpp
#include "stdafx.h"
#include<iostream>
using namespace std;
template<typename TT> void gg(const TT &t)
{
cout << 222 << endl;
}
template<typename TT> void ggg(const TT &t)
{
cout << 333 << endl;
}
主程序如下:
//主程序如下
#include "stdafx.h"
#include<iostream>
#include"head.h" //这里是函数模板的头文件名称
#include<string>
using namespace std;
int main()
{
string z("I am Chinese");
gg(z); //调用函数模板
ggg(z); //调用函数模板
system("pause");
return 0;
}
在VS中,函数模板可以用包含编译的方法去写代码,但是类模板却不可以这么做(反正我是没做出来),我把类模板的定义放在了头文件中,把函数模板的定义放在对应的源文件中,这样做也是可以的,在此只举出头文件的代码例子:
//头文件head.h,包含类模板的声明和定义,函数模板的声明。
//函数模板的定义放在了对应的源文件里,和上面的head.cpp内容一样
#ifndef TEMPLATE_DEMO_01
#define TEMPLATE_DEMO_01
template<typename TT> void gg(const TT &t);
template<typename TT> void ggg(const TT &t);
template<class Type>
class A
{
private:
int x;
public:
A() :x(0) {};
template<typename TT> void g(const TT &t);
int f();
};
template<class Type>
int A<Type>::f()
{
cout << x << endl;
return 55;
}
template<class Type> template<typename TT>
void A<Type>::g(const TT &t)
{
cout << t << endl;
}
#include"head.cpp" //记得加源文件
#endif //
2.2 在网上我发现了一个不错的代码,可以将模板的声明与定义完全分开,在主程序中包含源程序即可:
//head.h 模板声明
#pragma once
#ifndef TEMPLATE_DEMO_01
#define TEMPLATE_DEMO_01
template<typename T> void fun(const T &t);
template<class Type>
class A
{
private:
int x;
public:
A() :x(0) {};
template<typename TT> void g(const TT &t);
int f();
};
//#include"head.cpp" //这里不再需要包含源程序
#endif // !1
头文件对应的源程序里面,包含对函数模板和类模板的具体定义:
//head.cpp 模板的定义
#include "stdafx.h"
#include<iostream>
#include"head.h" //这里包含模板声明的头文件
using namespace std;
template<typename T> void fun(T &t)
{
cout << t << endl;
}
template<class Type>
int A<Type>::f()
{
cout << x << endl;
return 55;
}
template<class Type> template<typename TT>
void A<Type>::g(const TT &t)
{
cout << t << endl;
}
主程序中代码如下:
// main.cpp: 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<iostream>
#include"head.cpp" //注意:这里包含的是模板的定义的源文件,不是模板声明的头文件
#include<string>
using namespace std;
int main()
{
int x = -666;
short y =1;
string z("I am Chinese");
fun(x); //调用函数模板
fun(y); //调用函数模板
fun(z); //调用函数模板
A<int> a; //类模板实例化
a.f(); //对象a调用函数
a.g(z); //对象a调用函数模板
system("pause");
return 0;
}
2.3 分别编译模型,这里用关键字export进行声明,但是VS不支持关键字的这种使用方法,所以小心啊小心。