如何不使用dynamic_cast检查对象是否为指定祖先类型?
不用dynamic_cast检查对象是否为指定类或其派生类实例
当然可以,下面给你两种可行的实现方式,不过都各有局限:
方法一:给类添加虚类型判断函数
直接在基类里定义一个虚函数,用来标识对象是否属于目标类或其派生类。这种方式需要修改类的代码,但逻辑直观:
#include <iostream> struct Base { virtual ~Base() {} virtual bool isDerivedFamily() const { return false; } }; struct Derived : Base { bool isDerivedFamily() const override { return true; } }; struct DerivedAgain : Derived{}; struct OtherDerived : Derived{}; struct UnrelatedDerived : Base{}; int main() { Base* b1 = new DerivedAgain; Base* b2 = new UnrelatedDerived; if (b1->isDerivedFamily()) std::cout << "b1 属于 Derived 家族\n"; else std::cout << "b1 不属于 Derived 家族\n"; if (b2->isDerivedFamily()) std::cout << "b2 属于 Derived 家族\n"; else std::cout << "b2 不属于 Derived 家族\n"; return 0; }
这种方式的好处是性能比dynamic_cast好,而且完全不依赖dynamic_cast。派生类默认会继承父类的虚函数返回值,所以新增Derived的子类时,只要不刻意重写该函数,就能自动被识别为家族成员。
方法二:预存目标类家族的typeid集合
如果你不想修改类结构,可以预先把Derived及其所有派生类的type_info存到一个集合里,运行时直接对比当前对象的typeid是否在集合中:
#include <typeinfo> #include <iostream> #include <unordered_set> struct Base { virtual ~Base() {} }; struct Derived : Base{}; struct DerivedAgain : Derived{}; struct OtherDerived : Derived{}; struct UnrelatedDerived : Base{}; int main() { // 预先收集所有属于Derived家族的类型信息 const std::unordered_set<const std::type_info*> derivedFamily = { &typeid(Derived), &typeid(DerivedAgain), &typeid(OtherDerived) }; Base* b1 = new DerivedAgain; Base* b2 = new UnrelatedDerived; if (derivedFamily.count(&typeid(*b1))) std::cout << "b1 属于 Derived 家族\n"; else std::cout << "b1 不属于 Derived 家族\n"; if (derivedFamily.count(&typeid(*b2))) std::cout << "b2 属于 Derived 家族\n"; else std::cout << "b2 不属于 Derived 家族\n"; return 0; }
这种方式不用修改原有类结构,但缺点很明显:每新增一个Derived的派生类,都要手动把它的typeid加到集合里,维护成本高;如果有外部库的派生类,你根本没法提前收集这类信息。
额外说明
这两种方式都没法像dynamic_cast那样自动遍历整个继承链完成检查,dynamic_cast的核心优势就是无需手动维护类型列表,能自动识别所有合法的派生类。如果不是有特殊限制,dynamic_cast其实是最省心的方案——你也提到这可能反映代码设计问题,不过既然要替代方案,上面两种可以按需选用。
内容的提问来源于stack exchange,提问作者Romário
相关产品推荐
相关产品推荐

