dynamic_cast understanding
dynamic_cast understanding
我最近开始dynamic_cast和static_cast。我确实有点了解static_cast发生的事情,但不是dynamic_cast发生的事情。我所知道的最多的是static_cast可用于转换数据类型,并且不检查编译时,但dynamic_cast可以。我也使用动态强制转换编写了代码,但我不确定它们之间的关系。 这是我的代码
#include <iostream>
using namespace std;
class Base{
public:
virtual void setting(){
cout << "Hello, I am a function from the base class" << endl;
}
virtual void say(){
cout << "Base class says hi" << endl;
}
};
class Child:public Base{
public:
void setting(){
cout << "Hello, I am a function from the child class" << endl;
}
void say(){
cout << "Child class says hi" << endl;
}
};
class Child2:public Base{
public:
void setting(){
cout << "Hello, I am a function from the child2 class" << endl;
}
void say(){
cout << "Child class says Wazuppppp" << endl;
}
};
void start(Base* bp){ //here is where I get confused
Child* it_is_Child= dynamic_cast<Child*>(bp);
if(it_is_Child){
it_is_Child->say();
it_is_Child->setting();
}
Child2* it_is_child2= dynamic_cast<Child2*>(bp);
if(it_is_child2){ //then
it_is_child2->say();
it_is_child2->setting();
}
};
int main(){
Child cp1;
Child2 cp2;
start(&cp2);
cout << endl;
start(&cp1);
system("pause");
return 0;
}
令人困惑的是,子cp1和Child2 cp2与启动功能的关系以及它们如何工作。此外,编译器如何决定选择哪一个。
如果关联的类不相关(其中一个从另一个继承,或者两者都从共同祖先继承),则static_cast
将在编译过程中生成错误。
dynamic_cast
将在运行时返回一个空指针,如果转换类不是转换对象的确切类。
为了使dynamic_cast
正常工作,转换类必须声明至少一个虚函数。这是因为dynamic_cast
使用转换对象的 V-Table 指针,并且对象仅在其类声明虚函数时才具有 V-Table 指针。
比如Child* it_is_Child = dynamic_cast<Child*>(bp)
的幕后花絮是:
if (bp->__vfptr == Child::vftable)
return (Child*)bp;
return nullptr;
请注意,在某些编译器上,您还需要在项目设置中启用 RTTI。
在这种特殊情况下,如果不使用dynamic_cast
,您将获得完全相同的结果(事实上,当您拥有从基类继承的对象时,这就是您通常要做的事情)。换句话说:
void start(Base* bp){ //here is where I get confused
bp->say();
bp->setting();
};
会调用正确的say
并setting
.(当然,在这种情况下,如果您使用base
对象调用它,它也将从base
输出)。
如果有一个情况会更有趣child2
,例如,具有与其他类不同的功能集。
因此,如果我们这样做:
class Child2:public Base{
public:
void setting(){
cout << "Hello, I am a function from the child2 class" << endl;
}
void say(){
cout << "Child class says Wazuppppp" << endl;
}
void special() {
cout << "Special function called" << endl;
}
};
现在,如果我们这样做,函数special
在base
中不可用,但我们可以执行以下操作:
Child2 *it_is_child2 = dynamic_cast<Child2*>(bp);
if (it_is_child2)
{
it_is_child2->special();
}
dynamic_cast
的工作方式是编译器生成代码,该代码在运行时"查看"输入并确定它是否是"正确的类型"(即,类以正确的方式与要强制转换到的类相关)。通常,为了方便起见,它通过查看对象 vtable 来执行此操作,因为具有相同基类的类具有可以匹配的 vtable。在某些实现中,改用 RTTI(运行时类型信息),但大多数实现使用"vtable"方法。
通常,在使用继承时,应谨慎使用dynamic_cast
(以及类型之间的其他强制转换)(并且"始终"检查结果)。
不是编译器决定哪一个。使用RTTI,编译器在Child
的对象中添加一些额外的信息(另一个隐式属性),这些信息记录了对象的实际类。可以使用typeid
检索这些额外信息。然后为电话
Child* child = dynamic_cast<Child*>(bp);
编译器生成一些指令,由于这些信息,在运行时,如果类不正确,则决定返回指向实际对象或NULL
的指针。类似的东西
if (typeid(*bp) == typeid(Child))
child = reinterpret_cast<Child*>(bp)
else
child = NULL;
注意:我在这里过度简化。实际上,dynamic_cast
在超类的整个格子下做了一些更复杂的事情。
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 错误:"cast"未命名类型void setCastDescription(std::string
- SFINAE: Understanding void_t and detect_if
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- Understanding void func(A())
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- Understanding reinterpret_cast
- Shared_ptr cast vs static_cast speed
- Understanding of static_cast in C++
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- C++ C++ 中的函数声明,键入 CAST
- Understanding glClearColor values
- static_cast会丢弃错误,但C风格的演员cast有效