问题描述
下面的代码检查来自 p
指针的对象是否来自类型 Student
,如果是这种情况,则执行 dynamic_cast。
但是为什么我们不能做一个 static_cast 呢?
我认为转换是安全的,因为我们检查了来自指针的对象是否来自正确的类型,并且 static_cast 更快。
void testRTTI (Persoon ∗p){
if (strstr (type id (∗p).name(),"Student")!=NULL){
Student ∗ s = dynamic_cast<Student ∗>(p) ;
s−>studeer();
}
else p−>doe();
}
解决方法
您可以删除 typeid
检查,并且只检查 dynamic_cast
是否返回 nullptr
:
void testRTTI (Persoon *p){
if (Student * s = dynamic_cast<Student *>(p); s != nullptr){
s->studeer();
} else {
p->doe();
}
}
我认为您对动态转换指针的作用有误解。对于 dynamic_cast<T*>
,它将首先检查传递给 dynamic_cast<T*>
的指针是否可以以有效方式转换为 T*
。这个测试并不比你的 typeid(*p).name()
贵(至少对于给定的情况不是),而且肯定比 strstr(typeid(*p).name(),"Student")!=NULL
便宜。
如果它不能转换为 T*
它将返回 nullptr
如果它可以转换它将返回相同的指针转换为 T*
这不需要是一个操作完全没有。
因此您的代码会进行两项检查,一项检查您的 typeid
,另一项检查 dynamic_cast
。
if (strstr(typeid (∗p).name(),"Student")!=NULL)
在两个方面存在缺陷。
-
函数
name()
返回一个实现定义的值,没有任何保证。该值可能会从一次运行更改为另一次运行,并且可能是一个随机字符串。 -
忽略第一个问题:如果您有另一个类,其中
typeid(...).name()
将返回一个也包含"Student"
的字符串怎么办?
这就是您拥有 dynamic_cast
的原因:
Student ∗ maybeAStudent = dynamic_cast<Student ∗>(p);
if(maybeAStudent != nullptr)
{ /* p is a Student,do student things*/ }
else
{ /* p is another Person,do person things */}
注意:dynamic_cast
仅在 Person
至少有一个虚函数时有效。