应直接使用 std::is_polymorphic_v,它是 C++ 标准唯一定义、编译期可判定、跨平台一致的多态类型判断方式,其他如检查虚函数、vptr、dynamic_cast 或 sizeof 均不可靠。

直接用 std::is_polymorphic_v<t></t>,其他方法都不靠谱。 它是 C++ 标准唯一定义、编译期可判定、跨平台一致的方式。手动检查虚函数、查 vptr、试 dynamic_cast 或看 sizeof 差异,全是陷阱。
为什么不能靠“有没有 virtual 函数”来判断
标准定义的“多态类型”(polymorphic type)要求:类至少有一个虚函数(含虚析构),且不是 union。但仅扫描语法远远不够——
- 模板特化可能在实例化时才引入虚函数
-
#define VIRTUAL virtual会让字符串匹配失效 -
using Base::func;可能继承虚函数而不显式写virtual -
struct A final { virtual void f(); };是多态类型,但无法被动态绑定——std::is_polymorphic_v<a></a>仍为true,因为它只回答“类型是否符合多态定义”,不预测运行时能否 override
std::is_polymorphic_v 的正确用法和常见误用
它是个变量模板(C++17 起),对完整类型求值,返回 bool 编译期常量:
struct A { virtual ~A() = default; };
struct B { ~B() = default; };
struct Cfinal : A {};
static_assert(std::is_polymorphic_v<A>); // ✅ true
static_assert(!std::is_polymorphic_v<B>); // ✅ false
static_assert(std::is_polymorphic_v<Cfinal>); // ✅ true —— 继承即多态
static_assert(std::is_polymorphic_v<int>); // ✅ false
容易踩的坑:
立即学习“C++免费学习笔记(深入)”;
- 在类定义体内写
static_assert(std::is_polymorphic_v<myclass>)</myclass>→ 失败,此时MyClass是不完整类型 - 模板中用 C++14 及以前写法:
std::is_polymorphic<t>::value</t>;C++17 起统一用std::is_polymorphic_v<t></t> - 它不关心虚函数是否被
override、是否可达、是否被调用,只看语言规则定义的“是否为多态类型”
为什么不能用 dynamic_cast<void>(ptr)</void> 或 sizeof 判定
这些是运行时或 ABI 相关行为,完全偏离“类型是否多态”的本质问题:
-
dynamic_cast<void>(ptr)</void>非空,只能说明该 具体对象 有虚表,不能说明类型本身是否多态(比如空基类优化后sizeof可能为 1,但仍是多态类型) -
sizeof差异受 ABI 影响极大:Itanium ABI 下带虚函数的空类通常是 8 字节(含vptr),MSVC 可能不同;无虚函数但有虚基类也可能增大尺寸 - 试图读取对象首字节判断
vptr存在?未定义行为,且现代编译器可能优化掉虚表指针(如全内联无动态绑定场景)
最易被忽略的一点:std::is_polymorphic_v 对前置声明类型直接使用会触发硬错误(hard error),不是 SFINAE 友好型;若需在模板中安全探测,得配合 std::is_complete_v 先判完整类型,否则编译直接失败。


















