【发布时间】:2019-12-27 01:18:10
【问题描述】:
我刚开始与一个使用reinterpret_cast 的团队合作,显然它应该是dynamic_cast。尽管他们使用的是reinterpret_cast,但代码似乎仍然可以正常工作,所以我决定不理会它,直到最近它最终停止工作。
struct Base {
virtual void do_work() = 0;
};
struct D1 : public Base {
virtual void do_work();
std::vector<int> i;
};
struct D2: public D1 {
void do_work()
};
struct Holds_data {
std::vector<int> i;
};
struct Use_data : public Holds_data {
virtual void do_work();
};
struct A : public Use_data, public Base {
void do_work();
};
//case 1
// this code works
Base* working = new D2();
D2* d2_inst = reinterpret_cast<D2*>(working);
//case 2
Base* fail = new A();
A* A_inst = reinterpret_cast<A*>(fail); // fails
A* A_inst = dynamic_cast<A*>(fail); // works
在情况 1 中似乎没有问题,重新解释演员表似乎可以正常工作。 在案例 2 中,我注意到 std::vector 的内部数据在使用 reinterpret cast 时似乎已损坏
我的问题是为什么案例 1 通过了? std::vector 中不应该有数据损坏吗?
【问题讨论】:
-
未定义的行为可以做任何事情。这意味着有时它会做你期望的事情,有时它会做一些疯狂的事情。当 UB 按您的预期工作时,这是一个不幸的巧合。
-
显然不同的是在非工作情况下使用多重继承。但是正如已经说过的,两者都是错误的,但是当所有标准都说是未定义的行为时,您期望错误是不正确的。
-
重命名第二个
A_inst,然后打印出fail、A_inst和另一个A_inst的地址。你会看到一些神奇的东西。reinterpret_cast是对地址的字面重新解释。dynamic_casts 做一些不同的事情,更聪明。 -
reinterpret_cast(甚至是 C 风格的演员表)有它们的位置,并且有时(虽然很少)是正确的做法。 大多数时候他们是bugs - 就像在这种情况下。另请参阅:en.cppreference.com/w/cpp/language/ub 和 blog.llvm.org/2011/05/what-every-c-programmer-should-know.html 和 blog.regehr.org/archives/213
标签: c++ dynamic-cast reinterpret-cast