Mar*_*ard 5 c++ casting static-cast
我有以下小程序:
#include <iostream>
#include <map>
using namespace std;
class A {
public:
virtual void hello(int i)
{
cout << "A Hello " << i << endl;
};
};
class B {
public:
virtual void nothing() = 0;
};
class C : public A, public B {
public:
virtual void hello(int i) override
{
cout << "C Hello " << i << endl;
};
virtual void nothing() override
{
cout << "C Nothing " << endl;
}
};
int main() {
map<int, B*> map_;
A* testA = new C();
map_[0] = (B*)testA;
B* myB = static_cast<B*>(map_[0]);
myB->nothing();
C* testC = new C();
map_[1] = (B*)testC;
myB = static_cast<B*>(map_[1]);
myB->nothing();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
作为输出,我期待以下内容:
C Nothing
C Nothing
Run Code Online (Sandbox Code Playgroud)
但这是我得到的:
C Hello 0
C Nothing
Run Code Online (Sandbox Code Playgroud)
因此调用了错误的函数:即使在代码中从未调用过hello(int i),也会调用它.我知道它与演员有关,但我无法理解错误在哪里.
为什么要调用hello(int i)?
基类指针之间的转换(有时称为交叉转换)需要dynamic_cast.给定一个指针,A无法(静态地)知道它是C对象的一部分,因此无法静态地找到相应的B子对象.
你称之为"常规"演员是最危险的演员阵容.你永远不应该使用那种样式的强制转换(至少不要转换指针或引用).除了之外,它会强制使用任何演员来进行转换dynamic_cast.所以在这种情况下,它等同于reinterpret_cast假装B在与对象相同的地址处存在A对象.由于那里没有B(它在其他地方C),你会得到未定义的行为.
(具体的风格或未定义的行为可能是它使用包含nothing在a B中但实际上包含的虚拟表条目,hello因此最终调用它,并以一些未定义的值作为参数.但当然,未定义,任何事情都可能原则上发生.)