C++虚函数两种定义方式的区别及TouchGFX编译错误解析
TouchGFX开发中虚函数声明与定义的区别及编译错误解决
问题场景
- 基于TouchGFX开发多界面显示项目,项目包含全局
Model和ModelListener类,每个界面对应Presenter和View类 - 已完成PrincipalScreen相关类的实现,但SecondScreen的Presenter未正确处理
ModelListener中的虚函数 Model类的tick函数会通过ModelListener调用setTimeDate方法,触发时间更新通知
编译错误信息
./Application/User/gui/SecondScreenPresenter.o:(.rodata._ZTV21SecondScreenPresenter+0x28):undefined reference to `ModelListener::setTime(displayTime_t)'
解决方法
将ModelListener中的虚函数从仅声明改为带空实现的定义:
- 错误写法(仅声明):
virtual void setTime(displayTime_t time); // #1 报错 - 正确写法(声明+空定义):
virtual void setTime(displayTime_t time){} // #2 正确
两种写法的核心区别(结合C++与TouchGFX架构)
1. 仅虚函数声明(无定义)
这是普通虚函数的声明,但未提供实现代码:
- 编译器会为包含该函数的类生成虚函数表(vtable),但表中该函数的地址是缺失的
- 当子类(比如
SecondScreenPresenter)继承该类且未重写这个虚函数时,链接器找不到函数的实现,就会抛出"undefined reference"错误 - 在TouchGFX场景中,
Model通过ModelListener指针调用setTime时,会尝试找到该函数的实现,找不到就触发报错
2. 带空大括号的虚函数定义
这是同时完成了虚函数的声明与空实现:
- 编译器会把这个空实现的地址填入虚函数表
- 如果子类没有重写该函数,调用时会执行这个空实现,不会触发链接错误
- 对于暂时不需要处理时间更新的SecondScreen来说,这种写法既满足了链接器的要求,又不需要额外的逻辑代码
TouchGFX开发中的注意事项
ModelListener是TouchGFX中用于Model向各个Presenter推送数据更新的接口类,通常定义一系列虚函数- 如果你希望某个更新逻辑必须被子类实现,可以把该函数定义为纯虚函数(
virtual void setTime(displayTime_t time) = 0;),此时基类不需要实现,子类必须重写才能实例化 - 对于不需要处理的更新逻辑,用空实现的虚函数即可避免编译错误
内容的提问来源于stack exchange,提问作者Rodo
相关产品推荐
相关产品推荐

