when and why use explicit?

i'm sorry, but i fill much more confused :(
what is explicit and when use it?
i read some information and i tested, but i'm felling more confused :(
An explicit constructor can prevent unwanted implicit casting when creating an object.

For example,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Bar {
  public:
    /*explicit*/ Bar(int a) {  }
};

void foo(Bar b)
{
    
}

int main()
{
    foo(3); // error if constructor is explicit
    foo(Bar(3)); // works either way
}

The above code will compile just fine.

But, if you uncomment the explicit to the constructor, it will give you a compiler error.

So when to use it?

Allowing implicit casting can lead to behavior that the programmer might not expect to happen. Passing a 3 into a function that expects something other an an int can be confusing.

Here's another example:

Let's say you have a custom String class, and one of the constructors for this class take in an int, which signifies the amount of characters to reserve (allocate) for the string.
And then you have a print function that takes in a String.

Now, the user of your code wants to use your print function. They write writeLine(42); but nothing is printed!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Example program
#include <iostream>
#include <string>

class String {
  public:
    String(const char* c_str)
    : str(c_str)
    {
        
    }
    String(int n)
    {
        str.reserve(n);
    }
    
  private:
    std::string str;
    
    friend std::ostream& operator<<(std::ostream&, const String&);
};

// Operator overload to allow printing with cout << operator
std::ostream& operator<<(std::ostream& os, const String& str)
{
    return os << str.str;
}

void writeLine(String str)
{
    std::cout << str << "\n";
}

int main()
{
    writeLine(3);
}


But... let's add an explicit to the constructor.

1
2
3
4
    explicit String(int n)
    {
        str.reserve(n);
    }


Now, we get a compiler error. This error is good in that it prevents the user of your class/function from causing unexpected or ambiguous behavior.

1
2
3
4
 In function 'int main()':
36:16: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
7:5: note: initializing argument 1 of 'String::String(const char*)'
 


Maybe the user of the code should write writeLine("3"); instead.

This is a bit of a contrived example, but I hope it makes sense.
Last edited on
i did another sample:
writeLine(String(3));
with other words the explicit is for we use expecific type(inclued the String(something)) and avoid unexpected types.
like you show me how avoid the int for don't confuse with char(for exemple)... so, for test, i added the:
1
2
3
4
String (char chrValue)
    {
        str=chrValue;
    }

we can use char but never int...

unless we use the String():
writeLine(Strings(1));
i'm sorry, but what is for 'reserve'? is for convert the int to ASCCI table?
Do you mean the "reserve" in:

Let's say you have a custom String class, and one of the constructors for this class take in an int, which signifies the amount of characters to reserve (allocate) for the string.

Reserve as in reservation. Allocation.
1
2
3
4
String (char chrValue)
    {
        str=chrValue;
    }

Well, now, if you call writeLine(3), it's converting the int to a char, and then assigning that to the std::string.
3 is the ETX ASCII character, for End of TeXt, it's not a printable character.
This is a bit besides the point, maybe my second example was too complicated to be good.
My Bar example is more clear in the difference explicit makes.

Just remember: You can avoid this kind of confusion by also making the String(char) constructor, or any future constructors, be explicit as well. It prevents any casting of int to String or char to String or whatever under the hood.

std::string::reserve(n) just allocates space for n characters, but doesn't actually put anything in those spaces (doesn't change the string's length). I just used it for the example as an operation that doesn't actually affect the string you see.
Last edited on
thank you so much for all to all.
now i understand more about explicit. thank you so much
Topic archived. No new replies allowed.