C++学习笔记 模板 包含编译模式 分别编译模式
来源:互联网 发布:宏观经济数据分析 编辑:程序博客网 时间:2024/06/06 01:24
写过模板的朋友也许知道,一个模板程序,当编译器看到模板定义时并不立即产生代码,只有在我们用到模板,并对其实例化的时候,才会产生特定的实例。此时,编译器就要访问定义模板的源代码了。如果源代码不可访问,当然,编译器会报错的。记得我初学的时候,采用的是直接将声明和实现全部放在一个.h里面这个方法。但是,有时候我们确实想在.h文件中声明,在CPP文件中实现,从而实现文件分离。那么下面我就写写一般模板函数,模板类,模板特化的文件分离,我自己的心得。
- //
header file utlities.h - #ifndef
UTLITIES_H - #define
UTLITIES_H - template
<</span>class T >int compare(const T&, const T&); - ......
- #include
"utilities.cpp" - #endif
- //implementation
file utlities.cpp - template
<</span>class T> intcompare( constT const&v1, T &v2) - {
-
//implemente -
...... - }
(2)分别编译:
如果在头文件类声明中使用了export,则该头文件只能被源文件使用一次;如果在实现文件中使用了export,有下面两种用法
导出类
-
XXXXX.H 文件中 定义类 -
template <</span>typename Type> classTest{ }; -
// 在XXXXX.CPP 文件中 -
export template <</span>typename Type> classTest; - #include"XXXXX.h"
-
...//实现类成员<</span>
-
XXXXX.H 文件中 只声明 - template
<</span>typename Type> Type max( Type t1, Type t2 ); - //
在XXXXX.CPP 文件中 - //
模板定义 - export
template <</span>typename Type> - Type
max( Type t1, Type t2 ) {}
看到这儿,你也许心花怒放,似乎觉得如此简单。好,于是你回家敲代码,你会发现,你的编译器VS照样可能告诉你错了!
在头文件中
- #ifndef
tmp_h - #define
tmp_h - #include
- #include
- using
namespace std; -
- template<</span>typename
T> - class
Worker - {
- public:
-
typename vector::size_type sz; -
T test(const T& t1); - };
-
- #include
"tmp.cpp" - #endif
- #include"tmp.h"
-
- template<</span>typename
ch> - void
Display(string //这个函数是我在其他文件中实现的一个函数,不影响我们讨论的结果str); -
- template<</span>typename
T> - T
Worker::test(const T& t1) - {
-
string str = "worker::test is ;Running!" -
::Display<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char -
return t1; - }
- void
main() - {
-
Worker<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">int w1; -
w1.test(12.0); -
_getch(); - }
error C2995: 'T Worker::test(const T &)' :function template has already been defined
- #ifndef
tmp_cpp - #define
tmp_cpp - #include"tmp.h"
-
- template<</span>typename
ch> - void
Display(string str); -
- template<</span>typename
T> - T
Worker::test(const T& t1) - {
-
string str = "worker::test is ;Running!" -
::Display<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char -
return t1; - }
- #endif
也许,你以为就到此结束。编译问题似乎我们完全解决了。但是,另一种情况下,假若我们的模板函数包含一个模板的特化版本,采用这种策略,编译器仍然还是会报错。下面我们来看下面的代码:
//在func.h中我们声明了几个模板函数(采用如上所述的策略)
- #ifndef
FUNC_H - #define
FUNC_H - #include
- #include
- #include
- #include
- using
namespace std; -
- template<</span>typename
ch> voidDisplay(string str); - template<</span>typename
Type> voidWork(Type t1); - template<>void
Work<</span>int>( int t1); //Work的特化版本 -
- #include"func.cpp"
- #endif
- #ifndef
FUNC_CPP - #define
FUNC_CPP -
- #include
"func.h" -
- template<</span>typename
ch> - void
Display(string str) - {
-
ostream_iterator<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char ""); -
copy(str.begin(), str.end(), out_it); -
*out_it = '\n'; - };
-
- template<</span>typename
Type> - void
Work(Type t1) - {
-
string txt = "Work func ;nomal is runing !" -
Display<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char - }
- void
main() - {
-
typedef void (*PTEM)( doublet1); //定义一个指针调用一个,非特化版本的模板函数 -
PTEM pTem = Work; -
pTem(3232.0); -
Work<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">int - }
error LNK2005: "void __cdecl Work(int)"(??$Work@H@@YAXH@Z) already defined in func.obj
又是重定义!!我们明明都用了#ifndef
1.依然采用包含编译方法,这种方法最简单。只需要将特化版本的函数,声明称inline函数即可(其他的不变)。
- //头文件中
- template<>
inline void Work<</span>int>( int t1); - //cpp文件中
- template<>
- inline
void Work<</span>int>( int t1) - {
-
string txt = "now Work ;is special version." -
Display<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char - }
记住啊这里一定要加inline!
2.抛弃包含编译,采用以前的笨办法,将基本模板函数的实现全部放在头文件中,只在头文件中声明特化版本的函数。在CPP文件中只实现特化版本的函数。
- #ifndef
FUNC_H - #define
FUNC_H - #include
- #include
- #include
- #include
- using
namespace std; - /////////////////////////头文件中实现基本模板函数////////////////////////
- template<</span>typename
ch> - void
Display(string str) - {
-
ostream_iterator<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char ""); -
copy(str.begin(), str.end(), out_it); -
*out_it = '\n'; - };
-
- template<</span>typename
Type> - void
Work(Type t1) - {
-
string txt = "Work func ;nomal is runing !" -
Display<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char - }
- template<>
void Work<</span>int>( int t1); //特化版本的声明 -
- #endif
-
- ////////////////////CPP文件中只实现特化版本的函数////////////////
- #include
"func.h" - #ifndef
FUNC_CPP - #define
FUNC_CPP - template<>
- void
Work<</span>int>( int t1) - {
-
string txt = "now Work ;is special version." -
Display<<spanstyle="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px;BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px;PADDING-RIGHT: 0px; BORDER-TOP-STYLE: none; COLOR: #2e8b57;BORDER-LEFT-STYLE: none; FONT-WEIGHT: bold; PADDING-TOP:0px">char - }
-
- #endif
这样也能通过编译,也许你觉得第二个办法不高明。转来转去又回到了原点,所以要是不喜欢的话,还是推荐用第一种方法。
综上所述,我个人觉得,包含编译在模板程序中的确是首选,他很简单方便。(分别编译暂且不谈,因为不是每一个编译器都支持这种方式。)但是采用包含要注意有些特殊情况,如我上面例举出的例子。
FROM: http://blog.sina.com.cn/s/blog_40abd6640101ecf0.html
- C++学习笔记 模板 包含编译模式 分别编译模式
- C++ Template学习笔记之函数模板(5)——模板编译模式
- C++ Template学习笔记之函数模板(5)——模板编译模式
- C++学习:模板编译模式
- [转]C++ Template学习笔记之函数模板(5)——模板编译模式
- 模板的编译模式
- 模板的编译模式
- C++ 模板编译模式
- C++ 学习笔记 分别编译
- C语言编译模式
- C语言编译模式
- 模板与分离编译模式
- [C/C++不常见语法特性]_[模板编译模式]
- 模板的包含编译
- C++模板类的包含模式和编译错误的根本原因
- C中的内存模式(编译模式)
- C中的内存模式(编译模式)
- dev C++ 模板中的分别编译-- “包含”模型的一种解决方法
- 【日常学习】【搜索/递归】codevs2802 二的幂次方题解
- 在Python中使用Redis数据库
- 常用工具设置
- UISlider 的使用
- UnityShader实例08:溶解消融(Dissolve)材质
- C++学习笔记 模板 包含编译模式 分别编译模式
- HDU 1049 Climbing Worm
- VS OpenMP基础使用
- caffe study(2) 关于forward和backward - backward
- HP某型号打印机设计不当导致远程未授权打印漏洞
- C++ - 将模板的声明和定义放置在同一个头文件里
- 玩转单元测试之DBUnit
- 黑马程序员--第三天
- 可爱的验证码_java