C++拆分模板类到头文件与cpp文件时出现undefined reference编译错误
问题原因
- 基类非纯虚函数无实现
你在模板基类comm::Interface<T>中声明了非纯虚函数virtual void callbackMsg();,但全程没有给出该函数的实现代码。C++中只要类声明了非纯虚函数,就必须提供对应的实现,否则构建虚表时链接器无法找到对应函数地址,就会抛出你遇到的undefined reference错误。
- 基类非纯虚函数无实现
- 子类函数签名与基类不匹配,未完成重写
子类cameraInterface、lidarInterface中定义的callbackMsg都带有gazebo消息类型的参数,和基类无参的callbackMsg是完全不同的函数,属于重载而非重写。因此继承体系中基类的无参callbackMsg仍然属于没有实现的状态。
- 子类函数签名与基类不匹配,未完成重写
- 额外隐患:模板类的实现规则错误
C++模板类的成员函数实现必须和声明放在同一个头文件中,或者在cpp文件中显式实例化需要用到的模板类型,否则单独编译cpp时无法生成对应类型的模板实例代码,后续也会出现链接错误。你当前的模板基类只有接口没有额外实现,所以暂时没触发这个问题,后续加实现的时候需要注意。
- 额外隐患:模板类的实现规则错误
解决方案
根据你的业务场景(两个子类的回调参数类型不同,基类不需要统一的回调入口),推荐两种修复方案选其一即可:
方案1:删除基类多余的虚函数声明
直接删掉comm::Interface<T>类中的virtual void callbackMsg();这行声明即可,你子类的带参回调不需要和基类绑定,删除后不会影响现有功能,同时直接解决链接报错。
另外可以删掉communication.cpp中没用的COMM_CPP_GUARD头文件防护,cpp文件不需要加该逻辑。
方案2:修正虚函数设计,将基类函数改为纯虚函数
如果后续需要用基类指针统一调用回调接口,可以调整虚函数设计:
- 将基类的
virtual void callbackMsg();修改为纯虚函数:virtual void callbackMsg() = 0;,纯虚函数不需要基类提供实现,解决链接找不到实现的问题 - 调整子类实现,新增无参的
callbackMsg重写逻辑,原有带参的回调作为消息接收的入口函数,把收到的消息存到类成员变量后,无参callbackMsg负责处理已经存储的消息即可。
修复后重新编译即可解决问题。
内容的提问来源于stack exchange,提问作者pdaranda661
相关产品推荐
相关产品推荐

