\_ZTVxxx 未定义是虚函数表链接失败,主因是类的首个非内联虚函数(常为虚析构函数)未在 .cpp 中提供可链接定义;需用 c++filt 反解类名并检查虚函数实现、静态库包含及符号可见性。

为什么链接时报 _ZTVxxx 未定义?
这是典型的 C++ 虚函数表(vtable)链接失败错误。_ZTVxxx 是 GCC/Clang 对类虚表符号的 name mangling 名称(_ZTV 开头表示 vtable),说明链接器在最终合并目标文件时,找不到某个类的完整虚表定义。
根本原因不是“没写虚函数”,而是:该类有虚函数(包括析构函数),但它的首个非内联虚函数(通常是虚析构函数或第一个虚成员函数)没有在任何 .cpp 文件里提供可链接的定义。
常见诱因:
- 类声明在头文件中,所有虚函数都声明了,但没在 .cpp 中实现(尤其容易忽略虚析构函数)
- 虚函数被错误地标记为
inline或定义在头文件里却没加inline(导致 ODR 违反,多个 TU 各自生成弱符号但链接器无法合并) - 模板类误加了虚函数(模板类的虚函数不能是纯模板,必须显式实例化或定义在 .cpp 中)
- 使用了 PIMPL 但前置声明的类没正确定义虚析构函数
怎么快速定位是哪个类出了问题?
从报错的 _ZTVxxx 符号反解出类名:
立即学习“C++免费学习笔记(深入)”;
c++filt _ZTV8MyWidget # 输出:vtable for MyWidget
如果 c++filt 不可用,也可用在线 demangler(搜 “C++ symbol demangler”),粘贴 _ZTV... 字符串。
确认类名后,检查:
- 该类是否继承自带虚函数的基类?
- 是否声明了虚析构函数但没定义?
- 是否有纯虚函数但没标记
= 0,又没提供实现?
特别注意:即使类只有虚析构函数,也必须在 .cpp 中定义它(哪怕只写 MyClass::~MyClass() = default;),除非你把它声明为 default 且定义在类体内(此时编译器会隐式 inline,但需确保不违反 ODR)。
虚析构函数没定义是最常见原因
比如:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
// widget.h
class Widget {
public:
virtual ~Widget(); // ❌ 声明了,但没定义!
virtual void render() = 0;
};链接时就会报 _ZTV6Widget undefined。
正确做法:
// widget.h
class Widget {
public:
virtual ~Widget() = default; // ✅ 在类内 default → 编译器生成 inline 定义
virtual void render() = 0;
};或更稳妥(尤其涉及多态释放时):
// widget.h
class Widget {
public:
virtual ~Widget(); // 声明
};
// widget.cpp
#include "widget.h"
Widget::~Widget() = default; // ✅ 在 .cpp 中定义,确保唯一强符号注意:如果类有其他虚函数,也要保证其中至少一个非内联虚函数在 .cpp 中有定义——编译器通常把第一个非内联虚函数的定义所在 TU,作为整个虚表的“归属地”。
静态库 / 模块隔离导致虚表丢失
如果你把类定义在静态库(.a)中,而主程序只 include 头文件、没链接该库,也会触发此错。即使类定义完整,链接器看不到 .o 里的虚表符号。
验证方法:
nm -C libmylib.a | grep "vtable for MyWidget" # 如果无输出,说明该类的虚表根本没打进静态库
原因可能是:
- 编译静态库时漏编了含虚函数定义的 .cpp 文件
- 该 .cpp 文件被条件编译屏蔽(如
#ifdef BUILD_WIDGET但构建时未定义) - 使用了 LTO(-flto)但归档时未保留中间表示,导致虚表优化丢失(较少见,但可能)
解决:确保含虚函数定义的 .cpp 确实参与了静态库构建,并用 nm 或 objdump 确认符号存在。
虚表问题本质是链接期符号可见性问题,不是语法或运行时问题;盯住“哪个类、哪个虚函数没落地到目标文件”,比猜编译选项更直接。

















