板函数的定义和声明须在同一文件内

本文阐述了C++中模板函数的正确使用方式,强调模板函数的定义和声明必须位于同一文件内以避免链接错误。文章通过示例说明了为何遵循这一规则至关重要。

模板函数的定义和声明须在同一文件内

按照C++中代码的惯例,类声明在h文件中,类定义在cpp文件中,相应的成员函数声明也在h文件中,定义在cpp文件中。但是如果这样的架构用在模板函数中,在调用模板函数的地方链接器便会报错,error LNK2001: unresolved external symbol。将定义写在与声明相同的文件中问题解决,解释如下:

 

“大部分编译器在编译模板时都使用包含模式。也就是一般使用的把模板放到头文件中再包含。
当你不使用这个模版函数或模版类,编译器并不实例化它。当你使用时,编译器需要实例化它。因为编译器是一次只能处理一个编译单元,也就是一次处理一个cpp文件,所以实例化时需要看到该模板的完整定义,所以都放在头文件中。
这不同于普通的函数,在使用普通的函数时,编译时只需看到该函数的声明即可编译,而在链接时由链接器来确定该函数的实体。”

 

"temp.h:
void fun(T);

temp.cpp:
#include "temp.h"
void fun(T){}

main.cpp:
#include "temp.h"
void main()
{
    int a;
    fun(a);
}

由于main.cpp用到了fun(a),所以在编译main.cpp的时候,编译器知道它要用int来实例化fun(T)中的T,也就是要实例化fun(int),而要实例化一个函数模板就必须要知道这个函数模板的定义,但是由于main.cpp和包含函数模板定义的temp.cpp是分开编译的,所以编译器在编译main.cpp的时候就不能够用int来实例化fun(T),这样编译器就只能够把fun<int>(a)当成一个外部符号,交由linker来resolve。
另外编译器在编译temp.cpp的时候,同样因为temp.cpp和main.cpp是分开编译的,所以此时编译器并不知道main.cpp中用到了fun<int>(a),所以此时编译器虽然知道函数模板的定义,但也不会去实例化任何fun,当然就不会用int来实例化fun<T>了。
结果就是,你在main.obj引用了外部符号fun<int>,但是在temp.obj中不存在fun<int>,所以linker就会报告无法解析的外部符号了。"

### C语言中函数声明的作用及如何表示当前模块文件定义函数存在 在C语言中,函数声明的主要作用是向编译器提供有关函数的基本信息,包括函数名称、返回类型参数列表。这使得编译器能够在遇到函数调用时验证其正确性,并确保调用与函数定义相匹配[^1]。 当函数定义位于调用点之后时,必先进行函数声明,以使编译器能够识别该函数。例如,在同一文件中,如果`main`函数需要调用另一个函数`fun`,而`fun`的定义位于`main`之后,则应在`main`之前声明`fun`[^3]。 #### 函数声明的语法 函数声明的语法如下: ```c return_type function_name(parameter_list); ``` 例如,以下是一个简单的函数声明示例: ```c void greet(void); ``` 此声明告诉编译器,存在一个名为`greet`的函数,它不接受任何参数且返回类型为`void`。 #### 在同一文件定义声明函数同一文件定义声明函数时,通常将函数声明放在文件的顶部在使用该函数之前的位置。这样可以确保在调用函数时,编译器已经知道该函数的存在。例如: ```c // 函数声明 void fun(int a); int main() { int x = 5; fun(x); // 调用函数 return 0; } // 函数定义 void fun(int a) { printf("Value of a is %d\n", a); } ``` 在这个例子中,`fun`函数声明出现在`main`函数之前,因此可以在`main`中调用它,即使它的定义位于`main`之后[^3]。 #### `main`函数的特殊性 `main`函数是C程序的入口点,程序总是从`main`函数开始执行。尽管`main`函数本身不需要显式声明,但它必在程序中定义。如果没有`main`函数,编译器将无法找到程序的入口点,从而导致链接错误[^5]。 #### 头文件的作用 为了在多个文件之间共享函数声明,通常会将这些声明放在头文件(`.h`文件)中。其他源文件可以通过包含头文件来访问这些函数声明。例如,如果`fun`函数声明位于`a.h`文件中,则可以在`main.c`文件中通过`#include "a.h"`来使用`fun`函数[^3]。 ### 示例代码 以下是一个完整的示例,展示了在同一文件定义声明函数的过程: ```c // 函数声明 void displayMessage(void); int main() { displayMessage(); // 调用函数 return 0; } // 函数定义 void displayMessage(void) { printf("Hello from displayMessage!\n"); } ``` 在此示例中,`displayMessage`函数声明位于`main`函数之前,因此可以在`main`中调用它。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值