派生类调用非模板基类的模板成员函数出现链接错误的问询
如何在派生类中调用非模板基类的模板成员函数?
以下是相关代码文件:
Base.h
#pragma once #include <iostream> #include <stdint.h> class Base { protected: public: template <typename IntegerType> IntegerType test(); };
Base.cpp
#include "Base.h" template <typename IntegerType> IntegerType Base::test(){ IntegerType a = 0x0A; /* Some code here not related to issue */ return a; }
Derived.h
#pragma once #include <iostream> #include <stdint.h> #include "Base.h" class Derived: public Base { protected: public: void call(); };
Derived.cpp
#include "Derived.h" void Derived::call(){ this->test<int>(); // <- 编译错误 }
编译错误信息
/usr/bin/ld: /tmp/cc5KQsYX.o: in function `Derived::call()': Derived.cpp:(.text+0x14): undefined reference to `int Base::test<int>()' collect2: error: ld returned 1 exit status
疑问
为何编译器无法将模板实例化为int类型?已尝试以下写法但均无效:
this->template test<int>(); // 仍然无效
Base::test<int>(); // 仍然无效
问题原因与解决方法
这不是派生类调用的语法问题,而是模板成员函数的实现位置导致的链接错误。
C++模板的实例化要求编译器能获取模板的完整定义。你将Base::test的实现放在Base.cpp中,编译Derived.cpp时,编译器需要实例化test<int>,但此时它只能看到Base.h中的函数声明,无法获取模板的具体实现代码,因此无法生成对应的实例化代码;而编译Base.cpp时,编译器不知道后续需要test<int>的实例,也不会主动生成,最终链接阶段就会找不到该函数的定义。
有两种可行的解决方法:
- 将模板成员函数的实现直接放在头文件
Base.h中,与声明合并:
// Base.h #pragma once #include <iostream> #include <stdint.h> class Base { protected: public: template <typename IntegerType> IntegerType test(){ IntegerType a = 0x0A; /* Some code here not related to issue */ return a; } };
这样编译器处理Derived.cpp时,能直接读取模板的完整定义,即可正确实例化test<int>。
- 在
Base.cpp中显式实例化需要的模板版本:
// Base.cpp #include "Base.h" template <typename IntegerType> IntegerType Base::test(){ IntegerType a = 0x0A; /* Some code here not related to issue */ return a; } // 显式实例化int版本的模板函数 template int Base::test<int>();
这种方式会强制编译器在编译Base.cpp时就生成test<int>的实例化代码,链接阶段就能找到对应的函数定义。
另外补充:你尝试的this->template test<int>()写法,仅适用于基类是模板类的依赖名称场景,而你的基类是非模板类,所以该写法是多余的——原本的this->test<int>()语法本身是正确的,只是链接问题导致了报错。
内容的提问来源于stack exchange,提问作者Pavel
相关产品推荐
相关产品推荐

