implicit conversion

2019-08-12 00:54发布

问题:

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
}

回答1:

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
}


回答2:

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


回答3:

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



回答4:

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);