知道基类指针指向哪个派生类

Posted

技术标签:

【中文标题】知道基类指针指向哪个派生类【英文标题】:Knowing which derived class a base class pointer points to 【发布时间】:2015-11-24 06:02:44 【问题描述】:

假设我有一个 Animal 类和两个类 - Dog 和 Cat 派生自它。 这样做是完全合法的 -

Dog d;
Cat c;
Animal* a1 = &c;
Animal* a2 = &d;

现在,给定 a1 和 a2,我能知道这个指针指向哪个派生类吗?

我现在唯一的想法是在 Animal 类中再添加一个成员字段并在构造函数中对其进行初始化。这甚至是一个好习惯吗?

【问题讨论】:

不,这不是一个好习惯。这通常表明还有更多的事情要做。 【参考方案1】:

是的,它是合法的,是的,这是回到原始类型的一种方式。您也可以使用 dynamic_cast,但这有开销。一般程序将其存储在派生类型中,仅在无关紧要时与基类一起引用它。

我发现如果你必须做类似 dynamic_cast 的事情,你必须重新考虑你的程序设计。

【讨论】:

【参考方案2】:

您可以使用 dynamic_cast 找出答案。 Dynamic_cast 使用运行时类型检查,如果无法进行相应转换,则会失败。

ex: Derived* d = dynamic_cast<Derived*>(base)

另外,如果你使用 VStudio,你可以使用 typeid(*a1).name. 这会给你 a1 指针指向的类名。

【讨论】:

typeid 不仅仅是 Visual Studio 的东西。 不是假设我知道基指针的类型吗?在我的问题中,我会写Cat* ptr = dynamic_cast&lt;Cat*&gt;a1 还是Dog* ptr = dynamic_cast&lt;Dog*&gt;a1 是的。但是由于 dynamic_cast 是安全强制转换(检查运行时类型信息以确保可以进行有意义的转换),您将获得指向请求类型的有效指针或 null。如果你不知道指向的对象,那么使用 typeid(*a1).name="Cat" , typeid(*a1) == "dog"【参考方案3】:

我同意多米尼克的观点。我只想在这里补充两点,dynamic_cast 开销因编译器而异,如果您没有重新设计程序的选项,那么您别无选择,只能使用dynamic_cast。(以防万一(不是您的问题)如果您确定类型然后总是更喜欢使用static_cast,它的开销非常少。)

【讨论】:

这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review @Bartłomiej Semańczyk...答案是按照其他人的建议使用 dynamic_cast。【参考方案4】:

我建议添加一个字段。

正如其他人所提到的,dynamic_cast&lt;T&gt;() 可以使用,但您需要小心并知道它何时有效,何时无效。要让它工作,您需要 RTTI(运行时类型信息),它并不总是存在/有效(例如在使用库时等)

我同意@Dominic McDonnell:

我发现如果你必须做类似 dynamic_cast 的事情,你必须重新考虑你的程序设计。

PS:如果您使用的是 Qt,那么您可以使用 qobject_cast&lt;T&gt;(),因为 Qt 将此类信息添加到 QObject 类型的对象中而不需要 RTTI

【讨论】:

以上是关于知道基类指针指向哪个派生类的主要内容,如果未能解决你的问题,请参考以下文章

基类指针指向派生类对象&派生类指针指向基类对象

在 C++ 继承中,当指向基类的指针对象指向派生类时,不调用派生类析构函数

在基类对象内部创建派生类对象

为啥指向基类的派生类指针可以调用派生类成员函数? [复制]

使用具有指向派生类对象的指针的基类指针数组调用派生类方法

基类指针和派生类指针