I have heard that C++ has something called "conversion constructors" or "converting constructors". What are these, and what are they for? I saw it mentioned with regards to this code:
class MyClass { public: int a, b; MyClass( int i ) {} } int main() { MyClass M = 1 ; }
A constructor that is not declared with the specifier explicit and which can be called with a single parameter (until C++11) is called a converting constructor.
Sometimes constructors may take some arguments, or sometimes it does not take arguments. When a constructor takes only one argument then this type of constructors becomes conversion constructor. This type of constructor allows automatic conversion to the class being constructed.
In C++, if a class has a constructor which can be called with a single argument, then this constructor becomes conversion constructor because such a constructor allows automatic conversion to the class being constructed.
A Constructor in C is used in the memory management of C++programming. It allows built-in data types like int, float and user-defined data types such as class. Constructor in Object-oriented programming initializes the variable of a user-defined data type. Constructor helps in the creation of an object.
The definition for a converting constructor is different between C++03 and C++11. In both cases it must be a non-explicit
constructor (otherwise it wouldn't be involved in implicit conversions), but for C++03 it must also be callable with a single argument. That is:
struct foo { foo(int x); // 1 foo(char* s, int x = 0); // 2 foo(float f, int x); // 3 explicit foo(char x); // 4 };
Constructors 1 and 2 are both converting constructors in C++03 and C++11. Constructor 3, which must take two arguments, is only a converting constructor in C++11. The last, constructor 4, is not a converting constructor because it is explicit
.
C++03: §12.3.1
A constructor declared without the function-specifier
explicit
that can be called with a single parameter specifies a conversion from the type of its first parameter to the type of its class. Such a constructor is called a converting constructor.
C++11: §12.3.1
A constructor declared without the function-specifier
explicit
specifies a conversion from the types of its parameters to the type of its class. Such a constructor is called a converting constructor.
Why are constructors with more than a single parameter considered to be converting constructors in C++11? That is because the new standard provides us with some handy syntax for passing arguments and returning values using braced-init-lists. Consider the following example:
foo bar(foo f) { return {1.0f, 5}; }
The ability to specify the return value as a braced-init-list is considered to be a conversion. This uses the converting constructor for foo
that takes a float
and an int
. In addition, we can call this function by doing bar({2.5f, 10})
. This is also a conversion. Since they are conversions, it makes sense for the constructors they use to be converting constructors.
It is important to note, therefore, that making the constructor of foo
which takes a float
and an int
have the explicit
function specifier would stop the above code from compiling. The above new syntax can only be used if there is a converting constructor available to do the job.
C++11: §6.6.3:
A
return
statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list.
§8.5:
The initialization that occurs [...] in argument passing [...] is called copy-initialization.
§12.3.1:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.
Converting implicitly with converting constructor
Let's make the example in the question more complex
class MyClass { public: int a, b; MyClass( int i ) {} MyClass( const char* n, int k = 0 ) {} MyClass( MyClass& obj ) {} }
First two constructors are converting constructors. The third one is a copy constructor, and as such it is another converting constructor.
A converting constructor enables implicit conversion from argument type to the constructor type. Here, the first constructor enables conversion from an int
to an object of class MyClass
. Second constructor enables conversion from an string to an object of class MyClass
. And third... from an object of class MyClass
to an object of class MyClass
!
To be a converting constructor, constructor must have single argument (in the second one, second argument has one default value) and be declared without keyword explicit
.
Then, initialization in main can look like this:
int main() { MyClass M = 1 ; // which is an alternative to MyClass M = MyClass(1) ; MyClass M = "super" ; // which is an alternative to MyClass M = MyClass("super", 0) ; // or MyClass M = MyClass("super") ; }
Explicit keyword and constructors
Now, what if we had used the explicit
keyword ?
class MyClass { public: int a, b; explicit MyClass( int i ) {} }
Then, compiler would not accept
int main() { MyClass M = 1 ; }
since this is implicit conversion. Instead, have to write
int main() { MyClass M(1) ; MyClass M = MyClass(1) ; MyClass* M = new MyClass(1) ; MyClass M = (MyClass)1; MyClass M = static_cast<MyClass>(1); }
explicit
keyword is always to be used to prevent implicit conversion for a constructor and it applies to constructor in a class declaration.
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