奇怪的交叉播.这怎么可能
Strange cross-cast. How is it possible?
本文关键字:怎么可能 更新时间:2023-10-16
我试图了解这个奇怪的示例如何工作:
#include <iostream>
class A {
public:
virtual void f() {std::cout << "A::f()" << std::endl;}
};
class B : public A {
public:
void f() {std::cout << "B::f()" << std::endl;}
void h() {std::cout << "B::h()" << std::endl;}
};
class C : public A {
public:
void f() {std::cout << "C::f()" << std::endl;}
};
int main()
{
A* ap1 = new C();
auto bp1 = static_cast<B*>(ap1);
bp1->h();
A* ap2 = new C();
auto bp2 = dynamic_cast<B*>(ap2);
bp2->h();
return 0;
}
由于两种铸造的结果,它成功地称为B :: H()。完整输出为:
B::h()
B::h()
怎么可能?
一个常见的误解是,每当您取消NULL
指针时,都会得到SIGSEGV
。这是不真实的。相反,您会得到未定义的行为。
尤其是,如果您的代码删除指针,则允许编译器优化,好像当时不可能是NULL
。在这里,唯一可以从dynamic_cast
中获取非NULL
指针的情况是,如果它确实是B
的实例,因此编译器消除了检查。
用-fsanitize=undefined
编译以获得有意义的结果:
ub.cpp:22:35: runtime error: downcast of address 0x55c9736dcc20 which does not point to an object of type 'B'
0x55c9736dcc20: note: object is of type 'C'
00 00 00 00 48 fd c3 71 c9 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'C'
ub.cpp:23:11: runtime error: member call on address 0x55c9736dcc20 which does not point to an object of type 'B'
0x55c9736dcc20: note: object is of type 'C'
00 00 00 00 48 fd c3 71 c9 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'C'
B::h()
ub.cpp:27:11: runtime error: member call on null pointer of type 'struct B'
ub.cpp:27:11: runtime error: member access within null pointer of type 'struct B'
[1] 10583 segmentation fault (core dumped) ./ub
在两种情况下,行为均未定义。您的"成功调用B::h()
"只是该不确定行为的特殊表现。
您的第一个铸造static_cast<B*>(ap1)
本身就会立即产生未定义的行为。为了使此降低是有效的,指针ap1
必须指向某些B
对象的A
基本子对象。如果不是这种情况,则行为是不确定的。
您的第二个降低的行为定义了行为,但是在这些条件下,它"失败"了dynamic_cast
失败的方式:它返回一个空指针。但是,您尝试通过该空指针调用bp2->h()
。在那个阶段,行为变得不确定。
相关文章:
- 头文件可以在主类中运行.这怎么可能?
- 怎么可能只让设备使用 pjsua2 捕获或播放
- std::lock_guard 怎么可能比 std::mutex::lock() 更快?
- 怎么可能写 f( *this, std::forward<Args>(args)... ) 而 f 只用 F f 声明;
- 在QT C++编辑Qtable模型数据时,我需要得到一个小盒子,我需要显示编辑文本,这怎么可能?
- 在给定相同的输入的情况下,某些代码怎么可能花费更多时间来运行,这似乎只是因为它处于循环中?
- 答案怎么可能是433?
- 八进制文字怎么可能是负数?
- 我们可以在整数类型的双指针中分配2D整数数组的地址吗?怎么可能
- 我怎么可能从尚未定义某些成员方法的类创建实例?(C++)
- 使用 stl 迭代器封装向量是否很好?如果是?怎么可能呢?
- 几个比较怎么可能比一些计算慢
- 我的 Cuda 矢量怎么可能在填充后是空的
- 怎么可能有两个同名的变量——一个是全局变量,另一个是局部变量
- 奇怪的交叉播.这怎么可能
- 一个变量怎么可能既是constexpr又不是constexpr
- 如果方法私有,是否可以从 main 调用该方法?如果不是,怎么可能
- ANSI到Unicode或向后转换:怎么可能?
- std::unique_ptr怎么可能没有大小开销
- 在下面的示例中,函数对象"rev"是根据自身定义的。这怎么可能?