When designing a public API, is it a good practice to make the constructor as explicit?
class A { public: //explicit A(int i){} A(int i){} }; void fun(const A& a) {} int main() { // If I use explicit for A constructor, I can prevent this mistake. // (Or shall I call it as feature?) fun(10); }
Or shall I allow implicit conversion, to allow user to call my API with less typing?
The constructor should be explicit, unless an implicit conversion makes sense semantically (e.g. what is the meaning of converting an int to an A?). Less typing should not be the criterion to guide that decision. Think about readability (which is the main argument for implicit casting) and how well your code is to understand. An implicit cast that is not intuitive will make readers of the code scratch their heads.
P.S.: I cannot seem to come up with a good example right now, so any help is appreciated.
example for implicit conversion: anything numberlike (e.g. a bignum library, or a date/time library) – against implicit conversion: just consider the std::vector class that can be initialized with an initial size.
I agree with this. IME there's rarely ever a case where you want implicit casting and if you err on the explicit side, no harm is done by forcing users to a few more keystrokes.
As an example: implicit conversion from double to complex via complex(double re, double im = 0) makes sense, but conversion from int to vector via vector(int size) doesn't.
@Tadeusz: Even if it made sense, I'd advice against it. You forget one #include, and your code silently calls the wrong function. Writing complex(42.0) is so much easier than debugging late into the night to find such a bug.
@sbi: and that is why I am a bit wary of the new user-literals feature of C++0x, that one x behind your number can completely change its type may be useful... but the hell with readability. I would have preferred aliasing: using snsc = super::name::space::Create; which saves keystroke but brings in scoping etc...
|
11
Yes, by default any constructor, which can be called with one argument should be explicit. Following this rule will avoid subtle bugs, which are extremely hard to find.
Of course, there are exceptions to this rule:
Implicit conversion might be desirable, if your class has the semantics of a wrapper around the one parameter's type.
Copy and move constructors should not be explicit (otherwise you lose the possibility for pass-by-value calls).
This is what I found in a resonse from "Daniel Krügler"
If we would have started to design C++ from today on, there is a good chance, that all constructors and conversion functions were "explicit" by default, but a user could make the "implicit". Alas, the time cannot be turned back and we have to live with the current state. This means that we have to be careful in regard to implicit constructors (except for the copy/move constructor). It is a safer rule to make constructors explicit, where some form of conversion is involved (i.e. any constructor with an argument type U different from the actual type T).
Explicit constructors are used in classes, which consume significant resourses, like memory, construction time etc., to prevent user to create instances of such classes accidentally. It's up to you to decide, whether your class is "heavy" enough to use explicit constructor.
@Space_C0wb0y: accidental casting is your own fault for accidentally typing out a cast. Accidental implicit conversion is the issue here, surely.
2
It depends on the costs involved, both semantically and performance. If the creation of your class is expensive you should prevent it from being instantiated accidentally. If it's a cheap class to create then implicit construction can greatly simplify work for the API user.