This will work on most compilers. When you make a call to a method (non virtual), the compiler translates:
obj.foo();
to something:
foo(&obj);
Where &obj
becomes the this
pointer for foo
method. When you use a pointer:
Obj *pObj = NULL;
pObj->foo();
For the compiler it is nothing but:
foo(pObj);
i.e.:
foo(NULL);
Calling any function with null pointer is not a crime, the null pointer (i.e. pointer having null value) will be pushed to call stack. It is up to the target function to check if null was passed to it. It is like calling:
strlen(NULL);
Which will compile, and also run, if it is handled:
size_t strlen(const char* ptr) {
if (ptr==NULL) return 0;
... // rest of code if `ptr` is not null
}
Thus, this is very much valid:
((A*)NULL)->f2();
As long as f2
is non-virtual, and if f2
doesn't read/write anything out of this
, including any virtual function calls. Static data and function access will still be okay.
However, if method is virtual, the function call is not as simple as it appears. Compiler puts some additional code to perform late binding of given function. The late binding is totally based on what is being pointed by this
pointer. It is compiler dependent, but a call like:
obj->virtual_fun();
Will involve looking up the current type of obj
by virtual function table lookup. therefore, obj
must not be null.