why implicit conversion is harmful in C++

后端 未结 8 1621
臣服心动
臣服心动 2020-12-03 10:22

I understand that the keyword explicit can be used to prevent implicit conversion.

For example

Foo {

 public:
 explicit Foo(int i) {}
}


        
相关标签:
8条回答
  • 2020-12-03 10:42

    Mostly implicit conversion is a problem when it allows code to compile (and probably do something strange) in a situation where you did something you didn't intend, and would rather the code didn't compile, but instead some conversion allows the code to compile and do something strange.

    For example, iostreams have a conversion to void *. If you're bit tired and type in something like: std::cout << std::cout; it will actually compile -- and produce some worthless result -- typically something like an 8 or 16 digit hexadecimal number (8 digits on a 32-bit system, 16 digits on a 64-bit system).

    At the same time, I feel obliged to point out that a lot of people seem to have gotten an almost reflexive aversion to implicit conversions of any kind. There are classes for which implicit conversions make sense. A proxy class, for example, allows conversion to one other specific type. Conversion to that type is never unexpected for a proxy, because it's just a proxy -- i.e. it's something you can (and should) think of as completely equivalent to the type for which it's a proxy -- except of course that to do any good, it has to implement some special behavior for some sort of specific situation.

    For example, years ago I wrote a bounded<T> class that represents an (integer) type that always remains within a specified range. Other that refusing to be assigned a value outside the specified range, it acts exactly like the underlying intger type. It does that (largely) by providing an implicit conversion to int. Just about anything you do with it, it'll act like an int. Essentially the only exception is when you assign a value to it -- then it'll throw an exception if the value is out of range.

    0 讨论(0)
  • 2020-12-03 10:43

    Use explicit when you would prefer a compiling error.

    explicit is only applicable when there is one parameter in your constructor (or many where the first is the only one without a default value).

    You would want to use the explicit keyword anytime that the programmer may construct an object by mistake, thinking it may do something it is not actually doing.

    Here's an example:

    class MyString
    {
    public:
        MyString(int size)
            : size(size)
        {
        }
    
         //... other stuff
    
        int size;
    };
    

    With the following code you are allowed to do this:

    int age = 29;
    //...
    //Lots of code
    //...
    //Pretend at this point the programmer forgot the type of x and thought string
    str s = x;
    

    But the caller probably meant to store "3" inside the MyString variable and not 3. It is better to get a compiling error so the user can call itoa or some other conversion function on the x variable first.

    The new code that will produce a compiling error for the above code:

    class MyString
    {
    public:
        explicit MyString(int size)
            : size(size)
        {
        }
    
         //... other stuff
    
        int size;
    };
    

    Compiling errors are always better than bugs because they are immediately visible for you to correct.

    0 讨论(0)
提交回复
热议问题