C++中是否可将派生类Kernel指针作为基类Tensor方法的参数
结论
可以这么实现,但需要处理两个核心问题:循环头文件依赖、模板类的实现可见性。
注意事项1:解决循环依赖
你要在Tensor.hh中声明foo方法时,编译器需要先知道Kernel是一个存在的模板类,但不能直接在Tensor.hh中#include "Kernel.hh",否则会形成循环引用(Kernel.hh本身已经引入了Tensor.hh)。
正确做法是在Tensor.hh的Tensor类声明之前,加Kernel的前置声明:
// Tensor.hh 开头新增内容 template <class T> class Kernel;
仅声明函数参数为Kernel<T>*的场景下,前置声明足够让编译器通过语法检查,不需要Kernel的完整定义。
注意事项2:处理模板实现的可见性
C++模板的实现默认需要对调用方可见,你当前把模板类实现放在.cpp文件的写法,如果没有做显式实例化,会触发链接阶段的未定义错误,有两种解决方式:
方式一:把模板实现全部放到头文件中
包括Tensor<T>::foo的实现,以及Tensor、Kernel的其他模板方法实现,都直接写在对应的.hh文件里,这是最通用的处理方式。
示例修改后的Tensor.hh:
// Tensor.hh #pragma once template <class T> class Kernel; template <class T> class Tensor { public: void foo(Kernel<T>* kernel); /* 其余声明 */ }; // 实现直接写在头文件中 template <class T> void Tensor<T>::foo(Kernel<T>* kernel) { // 具体逻辑 }
方式二:在cpp文件中显式实例化所有需要用到的模板类型
如果你确定只会用到有限的几种模板参数类型(比如仅float、double),可以在对应的cpp文件中添加显式实例化声明,同时要注意Tensor.cpp需要引入Kernel.hh才能完成foo方法的编译:
// Tensor.cpp #include "Tensor.hh" #include "Kernel.hh" // 必须引入,才能编译foo方法中对Kernel的操作 template <class T> void Tensor<T>::foo(Kernel<T>* kernel) { // 具体逻辑 } // 显式实例化你要用的类型 template class Tensor<float>; template class Tensor<double>;
同理Kernel.cpp中也需要对Kernel做对应类型的显式实例化。
内容的提问来源于stack exchange,提问作者Mirco Mannino
相关产品推荐
相关产品推荐

