I understand that constructors with one (non-default) parameter act like implicit convertors, which convert from that parameter type to the class type. However, explicit
can be used to qualify any constructor, those with no parameters (default constructor) or those with 2 or more (non-default) parameters.
Why is explicit allowed on these constructors? Is there any example where this is useful to prevent implicit conversion of some sort?
One reason certainly is because it doesn't hurt.
One reason where it's needed is, if you have default arguments for the first parameter. The constructor becomes a default constructor, but can still be used as converting constructor
struct A {
explicit A(int = 0); // added it to a default constructor
};
C++0x makes actual use of it for multi parameter constructors. In C++0x, an initializer list can be used to initialize a class object. The philosophy is
if you use = { ... }
, then you initialize the object with a sort of "compound value" that conceptually represents the abstract value of the object, and that you want to have converted to the type.
if you use a { ... }
initializer, you directly call the constructors of the object, not necessarily wanting to specify a conversion.
Consider this example
struct String {
// this is a non-converting constructor
explicit String(int initialLength, int capacity);
};
struct Address {
// converting constructor
Address(string name, string street, string city);
};
String s = { 10, 15 }; // error!
String s1{10, 15}; // fine
Address a = { "litb", "nerdsway", "frankfurt" }; // fine
In this way, C++0x shows that the decision of C++03, to allow explicit on other constructors, wasn't a bad idea at all.