[Global Scope]
myClass *objA, *objB, *obj;
int objnum;
我想在objA
和objB
之间切换,并将其替换为obj
,因此在main()
我有:
int main()
{
objA = new myClass(parameters...);
objB = new myClass(parameters...);
// start with objA;
objnum = 0;
obj = objA;
}
在某些时候调用一个在两个对象之间切换的函数:
void switchObjects()
{
if (++objnum > 1) objnum = 0;
obj = objnum == 0 ? objA : objB;
}
在我使用该对象的函数中,我有:
void doYourJob()
{
int res = obj->work();
}
现在奇怪的是,如果我不将obj
分配给objA
或objB
,它仍然有效。相反,我会期待一个例外。即使我做obj = NULL;
,它仍然有效!什么是这个伏都教?
好的,我可以提供一个不同的示例,它会带来相同的结果,而不使用NULL指针:
myClass *obj[2];
int objnum;
void switchObject()
{
if (++objnum > 1) objnum = 0;
}
void doYourJob()
{
res = obj[objnum]->work();
}
int main()
{
obj[0] = new myClass(parameters...);
obj[1] = new myClass(parameters...);
objnum = 0;
}
使用上面的代码,无论objnum的值如何,我仍然可以让两个对象一起工作,即使我只在一个实例上调用work()
。
如果我用这个替换函数doYourJob()
:
void doYourJob()
{
int res1 = obj[0]->work();
int res2 = obj[1]->work();
}
我总是将结果加倍,好像我在每个对象上调用函数work()
两次。
答案 0 :(得分:4)
考虑一个更简单的例子:
#include <iostream>
struct X
{
void foo() { std::cout << "Works" << std::endl; }
};
int main() {
X* x = nullptr;
x->foo();
}
对于大多数编译器和大多数平台,尽管在空指针上调用foo
,但此代码似乎仍能正常工作。但是,该行为在技术上是 undefined 。也就是说,C ++语言对于执行此操作可能会发生的情况没有任何限制。
为什么会这样?好吧,调用成员函数只需要知道它被调用的对象的类型。我们知道x
指向X
,因此我们知道要调用的函数:X::foo
。在许多情况下,可能很难甚至不可能知道指针是否指向真实对象,因此编译器只是让它发生。在这种情况下,函数体实际上并不依赖于实际存在的X
对象,因此它只是起作用。这不是你可以依赖的东西。