📅 2010-Dec-17 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ constructors, cpp, explicit ⬩ 📚 Archive
A C++ constructor acts like an implicit type converter whenever it is needed. In the example below, the Foo( int )
constructor acts like an int-to-Foo type converter for the function doSomething
.
class Foo
{public:
int x ) { _val = x; }
Foo( private:
int _val;
};
void doSomething( const Foo &foo )
{}
10 ); // Acts like doSomething( Foo( 10 ) ); doSomething(
Only constructors with one non-default parameter can act like implicit convertors. That is, a constructor with only one parameter, which is not a default parameter. Or a constructor with many parameters, where the first parameter is not default and the rest of the parameters are default parameters. In the example below, the constructor with many parameters also acts like an implicit int-to-Foo convertor since all but one are default parameters.
class Foo
{public:
int x, int y = 99, int z = 999 ) { _val = x; }
Foo( private:
int _val;
};
void doSomething( const Foo &foo )
{}
10 ); doSomething(
With the inherent complexity of C++, most programmers do not want such implicit conversions happening under the hood. To prevent this from happening, the explicit qualifier can be used on such constructors. The example below does not allow implicit conversion.
class Foo
{public:
explicit Foo( int x ) { _val = x; }
private:
int _val;
};
void doSomething( const Foo& foo )
{}
10 ); // Error!
doSomething( 10 ) ); // OK doSomething( Foo(
A few notes:
The explicit qualifier can be used only with the constructor declaration, not the definition (if the two are separate).
The explicit qualifier can be used on any constructor. Even the default constructor or constructors with many non-default parameters. It is allowed for these, but does not seem to serve any purpose.
Since explicit prevents such under-the-hood activities, it is a good habit to apply it by default on all constructors. Turn it off only when you actually need an implicit conversion. 😊