In the following example, the author made several comments on the implicit conversion. Can you explain more detail on these comments, which are not very clear to me. Thanks.
class String{
explicit String(int n);
String(const char *p);
}
String s1= ‘a’; //error: no implicit char->String conversion
void f(String);
String g( )
{
f(10); // error: no implicit int->String conversion
return 10; // error: no implicit int-> String conversion
}
The author is documenting cases in which the compiler will give you an error because either there is no conversion, or the conversion selected is marked explicit
. The code might be clearer with a case that would actually work:
class String{
explicit String(int n);
String(const char *p);
};
String s1= ‘a’; //error: no implicit char->String conversion
// There is a combo implicit/explicit one...
// char (implicit) -> int (explicit) -> String
void f(String);
String g( )
{
f(10); // error: no implicit int->String conversion
// (the String(int n) constructor is marked explicit).
f("fred"); // not an error: uses the String(const char *) constructor
// for an implicit conversion.
f(String(10)); // not an error, explicitly calls the String(int n)
// constructor.
return 10; // error: no implicit int-> String conversion
}
The String
class has two constructors; one for constructing a String
from an int
and one for constructing a String
from a const pointer to a char
. These two constructors are hence also conversion functions, because they really convert one type into another. The first constructor, however, is an explicit constructor. While the second constructor allows for implicit conversion from a pointer-to-char
to a String
, the first constructor requires you to ask for the conversion explicitly.
For example:
String s;
s = 10; // error: implicit conversion from int to String
s = String(10); // ok: explicit conversion of int to String.
The first error comment simply says that there is no constructor for converting a char
to a String
. Again, we have only two constructors: one for converting an int
, the other a const pointer to char
.
The second error talks about passing as parameter an int
to a function that requires a String
. This implies that the function must construct a String
from an int
implicitly. This can't be done because the relevant constructor is explicit. If you'd construct a String
from an int
and then pass that String
to the function all would be well.
The third error is exactly the same as the second, only here the implicit conversion (which fails) is at returning an int
when the return value should be a String
.
One interesting thing to note is that the code would compile if the integer in your code would be 0 and not 10. The reason is that 0 can be implicitly casted to an address (the NULL address), and that is a valid value for the constructor that takes a pointer.
String s;
s = 0; // ok
s = '\0' // ok
The comments basically say that the compiler has no way of knowing how to convert to/from the String
datatype.
See: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr383.htm
Also: http://www.glenmccl.com/tip_023.htm
As addition info. first of all why we need to bother about the implicit conversion? Consider the following scenario.
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test ( int x);
~Test ();
void print ();
bool operator==(const Test &temp);
private:
int _x;
};
Test::Test (int x)
{
_x = x;
}
Test::~Test ()
{
}
void Test::print ()
{
cout <<"_x : "<<_x<<endl;
}
bool Test::operator==(const Test & temp)
{
cout <<"Comparing "<<_x <<" With "<<temp._x<<endl;
if (_x == temp._x) return 1;
else
return 0;
}
int main (int argc, char ** argv)
{
Test t1(10); //OK
Test t2 = 10; // We intented
t1.print (); /* Excellent */
t2.print ();
/* What we do not intend is this : silent Conversion from int to Object */
/* Hey man i forgot to mention t2, but mentioned '2' instead. */
if ( t1 == 2 )
cout <<"TRUE"<<endl;
else
cout <<"FALSE"<<endl;
}
It still compiled, and converted the integer '2' into Test Object, which was not my intention, but to compare t1 and t2. Using 'explicit' keyword infront of the single argument constructor, avoids such silent conversion. Hope this helps!!!..
explict test (int x);