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?
An explicit default constructor can be used to perform both default initialization and value initialization: the use of explicit with a default constructor has no effect unless it has default arguments that would allow it to be used in copy-initialization context.
Default Constructors: Default constructor is the constructor which doesn't take any argument. It has no parameters.
The following example defines a class with one constructor and two default constructors. You can declare default constructors as explicitly defaulted functions or deleted functions. For more information, see Explicitly defaulted functions (C++11) and Deleted functions (C++11).
Benefits. Supplying default constructor parameters has at least two benefits: You provide preferred, default values for your parameters. You let consumers of your class override those values for their own needs.
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.
Perhaps it was to support maintainance. By using explicit
on multi-argument constructors one might avoid inadvertently introducing implicit conversions when adding defaults to arguments. Although I don't believe that; instead, I think it's just that lots of things are allowed in C++ simply to not make the language definition more complex than it already it is.
Perhaps the most infamous case is returning a reference to non-static
local variable. It would need additional complex rules to rule out all the "meaningless" things without affecting anything else. So it's just allowed, yielding UB if you use that reference.
Or for constructors, you're allowed to define any number of default constructors as long as their signatures differ, but with more than one it's rather difficult to have any of them invoked by default. :-)
A better question is perhaps, why is explicit
not also allowed on conversion operators?
Well it will be, in C++0x. So there was no good reason why not. The actual reason for not allowing explicit
on conversion operators might be as prosaic as oversight, or the struggle to get explicit
adopted in the first place, or simple prioritization of the committee's time, or whatever.
Cheers & hth.,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With