Why NULL is converted to string*?
I saw the following code:
class NullClass {
public:
template<class T> operator T*() const { return 0; }
};
const NullClass NULL;
void f(int x);
void f(string *p);
f(NULL); // converts NULL to string*, then calls f(string*)
Q1> I have problems to understand the following statement
template<class T> operator T*() c开发者_运维百科onst { return 0; }
Specially, what is the meaning of operator T*()
?
Q2> Why f(NULL)
is finally triggering the f(string*)
?
Thank you
what is the meaning of
operator T*()
?
It is a user-defined conversion operator. It allows an object of type NullClass
to be converted to any pointer type.
Such conversion operators can often lead to subtle, unexpected, and pernicious problems, so they are best avoided in most cases (they are, of course, occasionally useful).
Why
f(NULL)
is finally triggering thef(string*)
?
NULL
is of type NullClass
. It can't be converted to an int
, but the user-defined conversion NullClass -> T*
can be used to convert it to a string*
, so void f(string*)
is selected.
Note that this works because there is only one overload of f
that takes a pointer. If you had two overloads,
void f(int*);
void f(float*);
the call would be ambiguous because the NullClass -> T*
conversion can be converted to both int*
and float*
.
template<class T> operator T*()
means that there is an implicit conversion from NullClass
to T*
for any T
.
When you're calling f(NULL)
, the compiler needs to decide which overload to use. Since neither overload takes an object of type NullClass
, it looks which implicit conversions exist. There is no conversion to int
, but there is one to string*
, so the conversion is applied and the string*
overload is called.
operator Anything()
overloads the "cast" operator. Whenever NullClass needs to be converted to Anything, this function will be called, and the result will be used.In your case, Anything is
T*
where T can be any type (it is a template parameter), meaning a NullClass supports casting to any pointers.Since NullClass can be cast into any pointers, including a
string*
. So thef(string*)
version will be used.
Q1> I have problems to understand the following statement
template<class T> operator T*() const { return 0; }
Specially, what is the meaning of
operator T*()
?
It's an implicit conversion operator. It makes it possible to have objects of the type it belongs to implicit convert to the target type T*
here. This version is a special one, since, being a template, it can convert an object of that NullClass
to any pointer type.
Implicit conversion are frowned upon for good reasons. They have the bad habit of kicking in at unexpected moments, making the compiler call an unintended version of an overloaded function. Having a templatized implicit conversion operator is especially evil because templatization multiplies the possibilities.
Q2> Why f(NULL) is finally triggering the f(string*)?
See above. There is no possible conversion to int
, so the implicit conversion operator kicks in and converts an NullClass
object into any pointer requested.
I suppose this is intended. Usually you don't want a pointer to be converted to an integer, which is why that class has an implicit conversion into any pointer, but none to int
.
That NullClass
isn't all that bad, but the NULL
instance of it is pure stupidity. As soon as you include any of the many headers that define the NULL
macro (defined to be 0
, i.e. an integer constant), the preprocessor will trample over all source and replace each usage of NULL
with 0
. Since you can't avoid to include this, this error renders the whole class pretty much useless.
The NuLLClass provides a conversion function to convert to a pointer. When you call f(NULL)
, it will try to find a way to convert NULL to a valid argument for f.
Because you can call operator T*()
on NULL, it will with T=string. This fulfills the demand for f(string *)
. Since there is no way to convert NULL to an int, there is only one clear choice of which function to call.
Specially, what is the meaning of
operator T*()
?
It is a conversion operator to type T*
. It allows operations such as (T*)NULL
.
Q2> Why f(NULL) is finally triggering the f(string*)?
Because the compiler looks for the best match between the arguments and the method's signature, in this case choosing template<typename T> NullClass::operator T*()
, where T=string
.
精彩评论