Problem understanding explicit constructor in C++
-
02-10-2019 - |
Question
After reading this thread What does the explicit keyword mean in C++?
I made up this program
class MyClass
{
public:
explicit MyClass(int a)
{
cout<<"Int was called"<<endl;
val = a;
}
MyClass(char *a)
{
cout<<"Char was called"<<endl;
val = atoi(a);
}
MyClass(const MyClass& copy)
{
cout<<"Copy Const was called"<<endl;
this->val = copy.val;
}
inline const int getval() const
{ return val; }
private:
int val ;
};
main code
int main()
{
int x=4;
char y='4';
char *z = &y;
MyClass a(x);
MyClass b(z);
MyClass c(a);
MyClass d('4');
cout<<a.getval()<<endl;
cout<<b.getval()<<endl;
cout<<c.getval()<<endl;
cout<<d.getval()<<endl;
return 0;
}
The output was:
Int was called
Char was called
Copy Const was called
Int was called
4
4
4
52
Now, as per thread above, it should throw error after the constructor call on object d but it didn't.
g++ version info
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
I am not sure if i have done something wrong in the above code. Please help
Solution
Explicit constructor will not allow you to do something like "implicit conversion", e.g. when initializing an object:
MyClass d = 4;
or when calling a function with parameters:
void foo( const MyClass& param);
...
foo( 4);
In your case, there is a conversion from char to int before calling the explicit constructor, which is as designed.
OTHER TIPS
Actually, constructing d
was done with the int
constructor. Your char
('4'
) was implicitly casted to an int
. This is legal in C/C++ since these are both integer numbers, with int
being at least as wide as char
(the other way round needs an explicit cast, as possible precision loss can result).
The output for object d
was the ASCII code for the character "4".
The explicit
keyword defines that the constructor is not available for implicit conversions, but in your code you are explicitly requesting the construction of the objects from the values.
If you change the code to:
MyClass d = 'a';
MyClass x = 5;
Then the conversion is implicit and you will get an error.
Note that the conversion that is important is not from 'a'
to int
but from int
to MyClass
. The compiler is allowed to perform the conversion from 'a'
to int
, as the MyClass(int)
constructor is explicitly requested in your original code.
'4' is a char, which is freely convertible to int. 52 is the character code for '4'
A "char" (as in 'd') has an int value in C++. Infact, 52 is the integer ASCII value of 'd'.
There is no error - it just invokes your int constructor with the integer value '4', which is actually U+0034 (Hex) or the number 52. All char constants in C/C++ are stored as int internally
Any char
literal is an int
, you can say int i = 'a
;`