Why avoid implicit type conversion?

Source: Internet
Author: User

The disadvantage of implicit type conversion by the compiler is greater than the benefit of implicit type conversion, so do not define the type conversion function unless you really need it.

Disadvantage of implicit type conversion: their existence may lead to errors.
For example:
Class Rational {
Public:
...
Operator double () const; // convert Rational class to double type
};
In this case, the function is automatically called:
Rational r (1, 2); // The r value is 1/2
Double d = 0.5 * r; // convert r to double and then perform multiplication.
Suppose you have a Rational Class As mentioned above. You want this class to have the function of printing Rational number objects, just as if it is a built-in type. Therefore, you may write as follows:
Rational r (1, 2 );
Cout <r; // print "1/2"
When the compiler calls operator <, it will find that such a function does not exist, but it will try to find a suitable implicit type conversion sequence to make the function call run properly. The rule definition of the type conversion sequence is complex, but in this case, the compiler will find that they can call the Rational: operatordouble function to convert r to the double type. Therefore, the printed result of the above Code is a floating point number, not a rational number. This is a disaster, but it shows the disadvantage of implicit type conversion: their existence will lead to errors.

The solution is to replace the conversion operator with functions that do not use the syntax keyword. For example, to convert a Rational object to a double type, use the asDouble function instead of the operator double function:
Class Rational {
Public:
...
Double asDouble () const; // convert Rational
}; // Double
This member function can be explicitly called:
Rational r (1, 2 );
 
Cout <r; // error! Rationa object does not have operator <
Cout <r. asDouble (); // correct. Use the double type to print the r

The method without declaring operators can overcome the disadvantages of implicit type conversion operators, but the single-parameter constructor is not that simple. After all, you really want to provide the caller with a single-parameter constructor. At the same time, you also want to prevent the compiler from calling this constructor without any authentication. Fortunately, there is a way to get both fish and bear's paw. In fact, there are two methods: one is an easy method, and the other is the method that must be used when your compiler does not support an easy method.
An easy way is to use the explicit keyword of a new compiler. It is easy to understand how to use this feature to solve implicit type conversion. The constructor declares with explicit. In this case, the compiler rejects calling constructor for implicit type conversion. Explicit type conversion is still valid:
Template <class T>
Class Array {
Public:
...
Explicit Array (int size); // note the use of "explicit"
...
};
Array <int> a (10); // correct. The explicit constructor can be used normally when an object is created.
Array <int> B (10); // correct
If (a = B [I])... // error! No way to implicitly convert int to Array <int>
If (a = Array <int> (B [I])... // correct, explicit conversion from int to Array <int> (but the logic of the Code is unreasonable)
If (a = static_cast <Array <int> (B [I])... // the same is true and unreasonable.
If (a = (Array <int>) B [I])... // The C-style conversion is correct, but the logic is still unreasonable.
In this example, static_cast (refer to the M2 clause) is used. spaces between two ">" characters cannot be missed. If the following is the case, write the statement:
If (a = static_cast <Array <int> (B [I])...
This is a statement with different meanings. Because the C ++ compiler uses ">" as a symbol to explain. There is no space between the two ">", and the statement will produce a syntax error.
If your compiler does not support explicit, you have to return to the single-parameter constructor that is not used as an implicit type conversion function.

As I mentioned earlier, complex rules determine which implicit type conversion is legal and which one is illegal. None of these rules can contain user-defined types (calling Single-parameter constructors or implicit type conversion operators ). You can use this rule to correctly construct your class so that the object can be constructed normally and remove the implicit type conversion you don't want.
Let's take a look at the array template. You need to use the integer variable as the constructor parameter to determine the array size, but at the same time, you must avoid implicit type conversion from the integer type to the temporary array object. To achieve this goal, you must first create a new class ArraySize. This object has only one purpose to indicate the size of the array to be created. You must modify the single-parameter constructor of Array and replace int with an ArraySize object. The Code is as follows:
Template <class T>
Class Array {
Public:
Class ArraySize {// This class is new
Public:
ArraySize (int numElements): theSize (numElements ){}
Int size () const {return theSize ;}
Private:
Int theSize;
};
Array (int lowBound, int highBound );
Array (ArraySize size); // pay attention to the new declaration
...
};
Here, ArraySize is nested into Array to emphasize that it is always used with Array. You must also declare that ArraySize is public so that anyone can use it.
Think about what will happen when an Array object is defined using a single parameter constructor:
Array <int> a (10 );
Your compiler requires that you use the int parameter to call the constructor in Array <int>, but this constructor is not available. The compiler realizes that it can be converted from the int parameter to a temporary ArraySize object. The ArraySize object is only required by the Array <int> constructor, so that the compiler performs the conversion. Function call (and object creation after it) is successful.
If you do not have an Array (ArraySize size) constructor, it is advantageous in some cases. Consider the following code:
Bool operator = (const Array <int> & lhs,
Const Array <int> & rhs );
Array <int> a (10 );
Array <int> B (10 );
...
For (int I = 0; I <10; ++ I)
If (a = B [I])... // alas! "A" should be "a [I]";
// Now it is an error.
To call the operator = function, the compiler requires the Array <int> object to be on the right side of "=", but if there is no single-parameter constructor whose parameter is int, then, the compiler cannot convert int into a temporary ArraySize object and then create a required Array <int> object through this temporary object. Therefore, the compiler will certainly produce an error when trying to compare it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.