views:

89

answers:

7

After reading this thread http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean

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

+1  A: 

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".

Daren Thomas
A: 

'4' is a char, which is freely convertible to int. 52 is the character code for '4'

Visage
+1  A: 

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.

David Rodríguez - dribeas
+4  A: 

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.

Cătălin Pitiș
Also there is no point in returning 'const int' from operator 'int' as cv qualified rvalues of fundamental types do not make sense. Am I right?
Chubsdad
A result by value is returned, so I see no point for const int.
Cătălin Pitiș
Yes, that is meaningless
Sashi
I never do it, but I have read some authors recommending it to avoid mistakenly changing the temporary in situations like `if ( foo() = 0 )` (when `==` was intended). For most such situations current compilers can be set to produce warnings so I have never really used it.
David Rodríguez - dribeas
That's why you could rephrase in a form some people hate: if( 0 == foo())
Cătălin Pitiș
A: 

A "char" (as in 'd') has an int value in C++. Infact, 52 is the integer ASCII value of 'd'.

Mr Shunz
A: 

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

m_pGladiator
A: 

Any char literal is an int, you can say int i = 'a;`

fastcodejava