我在尝试使用dynamic_cast时偶然发现了一些奇怪的行为。这是我的代码
struct Base
{
virtual ~Base(){}
virtual void output() = 0;
};
struct Derived1 : public Base
{
void output() {}
void doDerived_1()
{
std::cout << "derived 1\n";
}
};
struct Derived2: public Base
{
void output() {}
void doDerived_2()
{
std::cout << "derived 2\n";
}
};
int main()
{
Base* base = new Derived1();
Derived2* der2 = dynamic_cast<Derived2*>(base);
// der2 = 0
der2->doDerived_2();
}
即使der2等于0,仍会调用doDerived_2()并且其中的任何代码都将被执行。当我调用output()函数时,代码会中断。
有人可以向我解释为什么这种方法有效并且在明显不应该破坏的情况下不会破坏? 感谢
答案 0 :(得分:3)
您的代码具有未定义的行为,因为您正在取消引用空指针。
但是,成员函数调用的一种可能实现是通过thiscall calling convention,它隐含地将对象指针作为第一个参数传递。
如果您的函数不访问任何成员变量,则this
指针不会被取消引用,并且该函数可能会按预期执行。它与dynamic_cast无关。
请注意,标准
无法保证这一点示例:
struct Foo {
int doIt() {return 42;}
};
int main() {
Foo *f = NULL;
std::cout << f->doIt();
}
在某些编译器
上打印42答案 1 :(得分:2)
您正在取消引用空指针。这种操作的行为是不确定的。在这种情况下它恰好调用方法,this
是空指针。但是,任何事情都可能发生。
如果您想要抛出异常,请转换引号:
Derived2& der2 = dynamic_cast<Derived2&>(*base);
der2.doDerived_2();
或者,只有在转换成功时才能使用if语句执行某些代码:
if (Derived2* der2 = dynamic_cast<Derived2*>(base)) {
der2->doDerived_2();
}