如何判断指向某类的指针数组元素是否指向另一类的对象?
判断指向基类A的指针数组元素是否指向子类对象的方法
嘿,我来帮你搞定这个问题!首先得先指出你代码里几个会直接导致问题的小坑,然后再讲正确的判断方法~
先修正你代码里的错误
你的代码里有两个关键问题,不先解决的话根本没法正常运行:
- 类B的无限递归问题:你在
class B里定义了B ob;,这会导致创建B对象时,要先创建它的成员ob,而ob又是B类型,会无限嵌套实例化,直接栈溢出。改成指针B* ob;或者引用(需要提前初始化)就没问题了。 - 菱形继承的歧义问题:C同时继承了B和A,而B本身已经继承了A,这会让C里有两个A的实例,后续类型转换会出歧义。解决方法是用虚继承,让A在整个继承体系中只存在一个实例。
正确的判断方法:用dynamic_cast做运行时类型检查
C++里要判断基类指针实际指向的子类对象类型,最常用的就是dynamic_cast。它能在运行时检查类型转换是否合法:如果指针确实指向目标子类的对象,就返回该子类类型的指针;如果不是,就返回nullptr(指针类型的情况)。
不过有个前提:基类A必须包含至少一个虚函数(比如虚析构函数,这也是写基类的好习惯),因为dynamic_cast依赖运行时类型识别(RTTI),而只有带虚函数的类才会生成虚函数表,RTTI信息就存在这里。
修正后的完整代码示例
#include <iostream> // 基类A必须有虚函数,才能支持dynamic_cast的运行时类型检查 class A { public: virtual ~A() = default; // 虚析构函数,既避免内存泄漏,又支持RTTI // 可以添加其他成员函数 }; // 用虚继承避免菱形继承的歧义问题 class B : virtual public A { public: B* ob; // 改成指针,避免无限递归实例化 // B的其他成员 }; // 同样用虚继承A,确保A在C中只有一个实例 class C : public B, virtual public A { public: A* array[100]; // 指向A的指针数组 void check() { // 遍历数组中的每个指针 for (int i = 0; i < 100; ++i) { // 先跳过空指针,避免后续错误 if (array[i] == nullptr) { continue; } // 判断是否指向B类型的对象 if (B* b_obj = dynamic_cast<B*>(array[i])) { std::cout << "array[" << i << "] 指向一个B类型对象\n"; // 这里可以用b_obj操作B的成员,比如b_obj->ob } // 判断是否指向C类型的对象 else if (C* c_obj = dynamic_cast<C*>(array[i])) { std::cout << "array[" << i << "] 指向一个C类型对象\n"; // 这里可以用c_obj操作C的成员 } // 剩下的就是指向纯A类型的对象 else { std::cout << "array[" << i << "] 指向一个纯A类型对象\n"; } } } };
额外注意事项
- RTTI的开关:大部分编译器默认是开启RTTI的,但如果手动关闭了(比如GCC的
-fno-rtti选项),dynamic_cast就会失效,编译报错。 - 避免显式类型判断:面向对象设计的核心是多态,如果你只是想根据不同类型执行不同操作,最好是在基类里定义虚函数,子类重写,这样不用显式判断类型,代码更优雅也更易维护。比如在A里定义
virtual void doSomething() = 0;,然后B和C分别重写,直接调用array[i]->doSomething()就好。 typeid的替代方案:如果你只是想判断类型而不需要转换,也可以用typeid,比如if (typeid(*array[i]) == typeid(B)),但typeid返回的是精确类型,而且同样需要RTTI支持,灵活性不如dynamic_cast。
内容的提问来源于stack exchange,提问作者kik
相关产品推荐
相关产品推荐

