[GP]template必须定义于头文件中

C++模板函数需定义于头文件中
项目中A模块使用的模板函数在*.cpp中定义实现,VC6 sp5编译时,debug下正常,release下编写者处正常,其他人处编译不过。老板指出‘template必须定义于头文件中’,尝试后问题解决,《C++标准程序库》也有相关记载。

template必须定义于头文件中

最近在项目中遇到了一个奇怪的问题。

在程序中,A模块用到了一个模版函数,这个模版函数外部不需要调用,因此在*.cpp中定义并实现之。

编译的时候奇怪的现象发生了(VC6 sp5),在debug下,一切正常;在release下,在写这个模块的人那里可以正常编译且运行正常。可拿到我这来的时候,就编译不过了。我们几个师兄弟都没辙了,只能等老板来解决了。

“template必须定义于头文件中!”老板如是告诉我们。

试之,果不其然!

今日又看《C++标准程序库》,在p10页注释4,有记载:“目前template必须定义于头文件中....."。

[build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCaptureC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+0x1f8): undefined reference to `cv::Mat::~Mat()' [build] /usr/bin/ld: /usr/lib/aarch64-linux-gnu/libopencv_videoio.a(cap_gphoto2.cpp.o): in function `cv::gphoto2::DigitalCameraCapture::setProperty(int, double)': [build] (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0xe4): undefined reference to `gp_widget_get_type' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x11c): undefined reference to `gp_widget_set_value' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x150): undefined reference to `gp_camera_set_config' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x178): undefined reference to `gp_widget_set_changed' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x1ac): undefined reference to `gp_widget_get_choice' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x1c0): undefined reference to `gp_widget_set_value' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x258): undefined reference to `gp_widget_set_changed' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x2b8): undefined reference to `gp_widget_set_value' [build] /usr/bin/ld: (.text._ZN2cv7gphoto220DigitalCameraCapture11setPropertyEid+0x304): undefined reference to `gp_widget_set_value'上文中错误如何解决
最新发布
10-31
<think>好的,我现在需要回答用户关于C++模板函数在头文件定义的问题。用户的问题是:“带有模板函数的类是否需要在头文件中编写定义?”首先,我需要回忆C++模板的基本知识。 模板在C++中是编译时实例化的,这意味着编译器需要看到模板的完整定义才能为不同的类型生成具体的代码。普通函数和类的定义通常放在源文件中,然后在头文件中声明,但模板不同。如果模板的定义放在源文件中,当其他文件使用该模板时,编译器无法看到其实现,导致链接错误。因此,通常需要将模板的定义放在头文件中,以便在使用时能够被包含进来。 接下来,我需要确认用户提到的“带有模板函数的类”具体指什么。可能是指类中的成员函数是模板函数,或者类本身是模板类,而其中的成员函数需要定义头文件中。无论哪种情况,模板的定义都需要在头文件中。例如,模板类的成员函数如果在类外部定义,也需要在头文件中实现,否则在使用时会找不到定义。 还需要考虑显式实例化的情况。如果用户希望只在特定类型下使用模板,可以在源文件中显式实例化,这样头文件中只需声明,而定义放在源文件中。但这种方式限制了模板的通用性,只适用于已知类型的情况。大多数情况下,模板需要保持通用性,因此定义必须放在头文件中。 此外,可以引用用户提供的参考内容。例如,引用[1]中的`namespace test`和`std::sort`可能涉及模板的使用,说明标准库中的模板通常都是在头文件定义的。引用[2]中的宏定义虽然不直接相关,但强调了编译时处理的重要性,模板同样依赖编译时的实例化。 总结,模板函数和模板类的定义必须放在头文件中,以便编译器在实例化时能够访问完整的定义。显式实例化是例外情况,但通常不推荐,除非有特定需求。需要确保用户理解这一点,并提供示例代码说明如何在头文件中编写模板类及其成员函数的定义。</think>在C++中,**包含模板函数的类必须将模板定义放在头文件中**,因为模板的实例化需要在编译时可见。这是由C++的模板编译机制决定的:编译器需要看到完整的模板定义才能为不同的类型参数生成具体代码[^1]。 --- ### 具体规则说明 1. **编译单元可见性要求** 模板不是普通函数/类,它本质上是编译器生成具体代码的“蓝图”。如果模板定义在`.cpp`文件中,其他翻译单元使用该模板时将无法找到定义,导致链接错误: ```cpp // 错误示例:模板定义放在.cpp文件 // myclass.h template<typename T> class MyClass { public: void myMethod(T param); // 只有声明 }; // myclass.cpp template<typename T> void MyClass<T>::myMethod(T param) { /* 实现 */ } // 其他.cpp文件无法看到此定义 ``` 2. **正确做法** 将模板类及其成员函数的定义都放在头文件中: ```cpp // myclass.h template<typename T> class MyClass { public: void myMethod(T param) { // 直接在此实现 } // 或者在类外定义(仍需在头文件内) void anotherMethod(T param); }; template<typename T> void MyClass<T>::anotherMethod(T param) { /* 实现 */ } ``` 3. **显式实例化例外(特定场景)** 如果明确知道模板只会用于少数特定类型,可在`.cpp`文件中使用显式实例化: ```cpp // myclass.cpp template class MyClass<int>; // 显式实例化int类型 template class MyClass<float>; ``` 这种方式牺牲了模板的通用性,但能减少编译开销。 --- ### 设计原理 - **两阶段编译机制**:模板首次编译仅检查语法,实例化时再生成具体代码 - **跨翻译单元可见性**:头文件包含机制保证了所有使用者都能获取模板定义 - **与宏的本质区别**:模板是类型安全的编译器特性,而非文本替换(对比引用[2]中的宏展开问题) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值