The methods are actually normal functions that have a hidden parameter that is a reference to the instance you are using (it is this
). In case there is no instance whatsoever. No problem, the argument to be passed will be a null. But the function can be called, it has nothing to prevent because the function belongs to that class, the compiler knows that it exists. Something like this:
void pa(test * this) {
We can understand that basically all methods are static, what sets apart is just that hidden parameter, so they can be accessed in all circumstances (actually virtual methods can not because there is an indirection and would have to access the vtable that somehow is a member of the object state.
The problem would occur if within the function it tried to access some state member of the instance, implicitly or explicitly through this
. Then I would need to access the data somewhere in memory and it could not be null.
It works because it is not a technical impediment, but it is conceptually wrong, it is an "undefined behavior", there are no guarantees that it will always work on all platforms, so it is best to avoid this type of call.
This no longer works:
#include <iostream>
using namespace std;
class test {
int x = 0;
public:
void pa() {
cout << x << "NULL????" << endl;
}
};
int main() {
test * t = nullptr;
t->pa();
cout << "Hello world!" << endl;
return 0;
}
See not running on ideone .
The method is "compiled" like this:
void pa(teste *this) {
cout << this.x << "NULL????" << endl;
}
And beneath the cloths the call would be:
pa(&t); //lembrando que t é nulo
Notice why the error occurs? Calling the function is not a problem, accessing the parameter this
is.