给定一个指向其基类的指针,如何识别其子类?

9
假设我有一个抽象基类Parent和子类Child1和Child2。如果我有一个函数接受Parent*类型的参数,是否有一种方法(也许是通过RTTI),可以在运行时确定该函数实际接收到的是Child1*还是Child2*?
迄今为止,我的RTTI经验是,当foo是Parent*类型时,无论foo属于哪个子类,typeid(foo)都返回typeid(Parent*)。

2
一个 Parent* 总是一个 Parent*。它永远不会是一个 Child*。你想要问的是它所指向的东西的类型是什么。 - Kerrek SB
Kerrek SB:昨天我对你冷言冷语,但当我开始实际编程时,你的评论可能比页面上的任何其他内容都更有价值。对此感到抱歉... - ExOttoyuhr
3个回答

7

你需要查看解引用指针的typeid,而不是指针本身;也就是说,使用typeid(*foo),而不是typeid(foo)。询问解引用指针将获得动态类型;询问指针本身只会获得静态类型,正如你所观察到的那样。


这听起来比创建许多子类指针更符合我一直在寻找的要求... - ExOttoyuhr
值得一提的是,只有当父类至少有一个虚方法时,typeid(*foo)才会返回正确的运行时类型(即Child1而不是Parent)。 - ApproachingDarknessFish

5
您可以使用 std::dynamic_cast 来实现这个功能。
Parent* ptr = new Child1();
if(dynamic_cast<Child1*>(ptr) != nullptr) {
    // ptr is object of Child1 class
} else if(dynamic_cast<Child2*>(ptr) != nullptr) {
    // ptr is object of Child2 class
}

如果您使用智能指针,比如std::shared_ptr,可以这样检查:

std::shared_ptr<Parent> ptr(new Child1());
if(std::dynamic_pointer_cast<Child1>(ptr) != nullptr) {
    // ptr is object of Child1 class
} else if(std::dynamic_pointer_cast<Child2>(ptr) != nullptr) {
    // ptr is object of Child2 class
}

3

当然:

BaseClass *bptr = // whatever, pointer to base class
SubclassOne *safe_ptr_one = dynamic_cast<SubclassOne *>(bptr);
if (safe_ptr_one != nullptr) {
    // Instance of SubclassOne
} else {
    // not an instance of SubclassOne, try the other one
    SubclassTwo *safe_ptr_two = dynamic_cast<SubclassTwo *>(bptr);
    if (safe_ptr_two != nullptr) {
        // Instance of SubclassTwo
    } else {
        // it wasn't either one :'(
    }
}

不错 - 我不知道 dynamic_cast 可以做到那样!(但是,这就是为什么我问的原因。) - ExOttoyuhr
@ExOttoyuhr 不用谢。耶,我在Andy Prowl之前提供了答案! - user529758

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接