包含编译模型

来源:互联网 发布:sql to_char时间变了 编辑:程序博客网 时间:2024/05/10 22:09

对于一般的程序员,总是习惯把类、函数的声明放在头文件件中,而把它们的定义放在对应的源文件中(这个源文件要#include对应的头文件),在主程序中,包含头文件即可。这是因为,只要在编译时可以看到函数的声明,编译就能通过;类似的,定义一个类的对象时,类定义必须可用,但是类成员的就不一定必须定义好了,只要有声明就行。
但是对于函数模板或者类模板,这样做就行不通了。因为在实例化模板时,编译器必须能够访问定义模板的源代码(不论是函数模板还是类模板)。所以很多人都习惯于把模版类或者模板函数的声明和定义放在同一个文件中。但是,对于一些比较复杂的程序,这样的代码组织就略显凌乱。为此,C++编译模版的代码定义了两种模型,分别称为“包含”模型和“分别编译模型”。其中所有编译器都支持第一种,只有少量的支持第二种,所以这里重点讨论一下第一种应该如何使用。
其实很简单,编译器不就是想在实例化模板时可以看到模板的定义么?在声明模板的头文件中加入#include对应的源文件就行了,举个例子:
头文件test.h中放入模板函数的声明,并且包含对应的源文件:

#ifndef TEST_H#define TEST_Htemplate <class T> int compare(const T&,const T&);#include "test.cpp"#endif


在test.cpp中直接写上:

template<class T>int compare(const T &v1,const T &v2){if(v1 < v2)return -1;if(v2 > v1)return 1;return 0;}

此时在main函数中就能调用compare函数了。

但是对一些比较复杂程序,这样做就会引起函数的重复定义。具体的原因是因为:有的定义函数的源文件中,必须包含对应的头文件。此时,由于头文件又包含了源文件,导致编译时出现重复定义的现象发生。解决办法其实也很简单:把头文件对应的源文件从工程中移除(不是删除,文件还在,只不过不添加到工程里),这样的话,只会在编译头文件的时候编译一遍源文件,就不会出现重复定义的情况了。


 

原创粉丝点击