1 2 3 4 5 6
|
class String
{
public:
explicit String( char c, int count = 1 );
explicit String( const char* str, int start = 0, int count = -1 );
};
| |
First, "explicit" is only needed on constructors that can be called with exactly one parameter.
(Note all of the above can be, because all additional parameters are defaulted). Second, this
rule DOES NOT APPLY to the copy constructor; never make the copy constructor explicit.
To understand what explicit does, consider the following examples:
1 2 3 4 5 6 7 8 9 10 11 12
|
void foo( String s ) {
// ...
}
// Without "explicit", all of the following lines compile:
String s( "Hello World!" );
String s2( 'X' );
foo( s ); // Copy constructor is provided by compiler
foo( 'c' ); // Implicitly calls first constructor to make a String from a char
foo( "Hello World" ); // Implicitly calls second constructor to make a String from a const char*
// With "explicit" on both constructors, only the first two lines above compile.
| |
So it seems like using explicit just makes you type more, right? Well, the reason for explicit is
because sometimes you
don't want the compiler to perform the implicit construction. Why?
Because in a large program with a lot of classes, sometimes code compiles that you wouldn't
expect to compile thanks to the compiler diligently finding a series of implicit constructors it
can call.
For example, you have a function foo that takes an A as parameter. But somewhere in your
program you try to call it with a Z instance accidentally. You intended it to be a compile
error, but in fact, the compiler found that a B could be implicitly constructed from an A, and
a C implicitly constructed from a B, and an F from a C, a J from an F, etc, etc, until eventually
a Z could be made.
In small applications there isn't a whole lot of need for explicit. But for large apps it does make
sense. Since explicit only causes you to type a little bit more occasionally, I recommend that
programmers get into the habit of using explicit all the time. Only in certain very rare
circumstances do you want the implicit behavior (look at std::string for example).