I have an application involving objects of different class types. The objects are referenced by pointers. A null pointer signifies that the associated object does not exist. Currently the calling codes is cumbersome, because each time it uses a pointer to an object, it tests the pointer value for null, and take some appropriate action it is null. Because the default action to be taken in the case of non-existence depends on the type of object, I would prefer to encode it in the classes for the objects themselves rather than in the calling program. This results in constructions like the following:
class C
{ ...
void member_func() //non-virtual !
{ if (this) { do something with the object ... }
else { take some default action }
}
...
};
Clearly the member function cannot be virtual, because the lookup table does not exist when the object does not exist, and the virtual call would fail. But is this code legal C++ for non-virtual member functions? It seems to work correctly for the compilers I have tried it on, but I am worried about possible non-portability. In the standard I can’t find a clause that either expressly allows or expressly prohibits such constructions.
Standard-wise, the code is not legal, but it's used in practice (bad practice that is).
In fact, IIRC MFC uses these checks internally.
Checking whether
this == NULL
is not a problem. Calling a method through a NULL object pointer is.If you want to keep the checks somewhere, you could put it in a smart pointer class which can take the appropriate action if the held pointer is NULL. If the "appropriate action" is uniquely determined by the held type, you can use a traits class to specify it.
This way your NULL checks and their logic is kept together, and not mixed into either the caller or the method code.
Unfortunately, I can't see a way to do this without throwing. There's no way to intercept function calls for all methods names, otherwise I'd just return
*this
fromoperator->
and do the work inoperator()
.this
will never be null in a member function so the check you perform is useless.As pointed by Matthieu M. in a comment, if you do something like this in your code:
This would cause undefined behavior and that is something bad.
As has been pointed out,
this
can never be a null pointer. If it is, you've already invoked undefined behavior. You could, instead, create a set of overloaded functions, like this:If the function you want to call has the same name in each class, then you could make a static function in each class which performs the default action for that class (all with the same name), and make a template:
I think, it's not allowed to do that. You asked for references to the standard. I believe first thing of interest is 9.3.1 Nonstatic member functions, 1.:
Second let's look at 5.2.5 Class member access, 2.:
So if E1 is a nullptr, the *E1 will not be allowed. So at least is my guess.