why implicit conversion is harmful in C++

后端 未结 8 1620
臣服心动
臣服心动 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:35

    A real world example:

    class VersionNumber
    {
    public:
        VersionNumber(int major, int minor, int patch = 0, char letter = '\0') : mMajor(major), mMinor(minor), mPatch(patch), mLetter(letter) {}
        explicit VersionNumber(uint32 encoded_version) { memcpy(&mLetter, &encoded_version, 4); }
        uint32 Encode() const { int ret; memcpy(&ret, &mLetter, 4); return ret; }
    
    protected:
        char mLetter;
        uint8 mPatch;
        uint8 mMinor;
        uint8 mMajor;
    };
    

    VersionNumber v = 10; would almost certainly be an error, so the explicit keyword requires the programmer to type VersionNumber v(10); and - if he or she is using a decent IDE - they will notice through the IntelliSense popup that it wants an encoded_version.

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

    I use explicit as my default choice for converting (single parameter or equivalent) constructors. I'd rather have the compiler tell me immediately when I'm converting between one class and another and make the decision at that point if the conversion is appropriate or instead change my design or implementation to remove the need for the conversion completely.

    Harmful is a slightly strong word for implicit conversions. It's harmful not so much for the initial implementation, but for maintenance of applications. Implicit conversions allow the compiler to silently change types, especially in parameters to yet another function call - for example automatically converting an int into some other object type. If you accidentally pass an int into that parameter the compiler will "helpfully" silently create the temporary for you, leaving you perplexed when things don't work right. Sure we can all say "oh, I'll never make that mistake", but it only takes one time debugging for hours before one starts thinking maybe having the compiler tell you about those conversions is a good idea.

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

    It introduces unexpected temporaries:

    struct Bar
    {
        Bar();      // default constructor
        Bar( int ); // value constructor with implicit conversion
    };
    
    void func( const Bar& );
    
    Bar b;
    b = 1; // expands to b.operator=( Bar( 1 ));
    func( 10 ); // expands to func( Bar( 10 ));
    
    0 讨论(0)
  • 2020-12-03 10:37

    It's not harmful for the experienced. May be harmful for beginner or a fresher debugging other's code.

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

    To expand Brian's answer, consider you have this:

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

    This actually allows this code to compile:

    MyString mystr;
    // ...
    if (mystr == 5)
        // ... do something
    

    The compiler doesn't have an operator== to compare MyString to an int, but it knows how to make a MyString out of an int, so it looks at the if statement like this:

    if (mystr == MyString(5))
    

    That's very misleading since it looks like it's comparing the string to a number. In fact this type of comparison is probably never useful, assuming the MyString(int) constructor creates an empty string. If you mark the constructor as explicit, this type of conversion is disabled. So be careful with implicit conversions - be aware of all the types of statements that it will allow.

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

    "Harmful" is a strong statement. "Not something to be used without thought" is a good one. Much of C++ is that way (though some could argue some parts of C++ are harmful...)

    Anyway, the worst part of implicit conversion is that not only can it happen when you don't expect it, but unless I'm mistaken, it can chain... as long as an implicit conversion path exists between type Foo and type Bar, the compiler will find it, and convert along that path - which may have many side effects that you didn't expect.

    If the only thing it gains you is not having to type a few characters, it's just not worth it. Being explicit means you know what is actually happening and won't get bit.

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