我错误地写了一些愚蠢的东西,令我惊讶的是。
class A
{ public:
void print()
{
std::cout << "You can't/won't see me !!!" << std::endl;
}
A* get_me_the_current_object()
{
return this;
}
};
int main()
{
A* abc = dynamic_cast<A*>(abc);
abc->print();
}
这里,A* abc = dynamic_cast<A*>(abc)
,我在指针上做了dynamic_cast,但没有声明。但是,它有效,所以我认为上述陈述被打破为:
A* abc;
abc = dynamic_cast<A*>(abc);
因此,它的工作原理。但是,在尝试一些更奇怪的场景时,例如:
A* abc;
abc->print();
,进一步
A* abc = abc->get_me_the_current_object();
abc->print();
我惊呆了,看着这些例子是如何运作的,并且映射已经完成 有人可以详细说明这些是如何工作的吗?提前谢谢。
答案 0 :(得分:6)
你犯了一个常见的错误,认为未定义的行为和C ++错误意味着你应该期待看到一个戏剧性的崩溃或你的计算机着火。有时候没有任何事这并不意味着代码“有效”,因为它仍然有一个错误,只是症状没有出现...... 尚未。
但是,它有效,所以我认为上述陈述被打破为:
是的,你所做的只是将未初始化的指针转换为相同的类型,即不需要转换,因此编译器什么都不做。你的指针仍然是同一类型,仍未被初始化。
这与此类似:
int i = i;
根据C ++的语法,这是有效的,因为i
在此范围内,但是未定义,因为它复制了未初始化的对象。不太可能实际上让你的电脑着火,它似乎“有效”。
有人可以详细说明这些是如何运作的吗?
从技术上讲,你是取消引用一个无效的指针,这是一个未定义的行为,但由于你的成员函数实际上并没有使用该对象的任何成员,因此无法解除引用无效的this
指针,因此代码“有效” “(或者至少看起来像。)
这类似于:
void function(A* that)
{
std::cout << "Hello, world!\n";
}
A* p;
function(p);
因为没有使用that
指针(就像你的成员函数中没有使用this
指针一样),这不一定会崩溃,尽管它可能会在甚至复制未初始化指针的实现上发生可能会导致硬件故障。在您的示例中,您的编译器似乎不需要取消引用abc
来调用非静态成员函数,并将其作为隐藏的this
参数传递不会导致硬件错误,但行为仍然未定义,即使它没有以明显的方式失败,例如段错误。
答案 1 :(得分:3)
abc
未初始化并指向内存中未定义的位置,但您的方法无法读取*this
中的任何内容,因此它们不会崩溃。
它们不会崩溃的事实几乎肯定是实现定义的行为。