tags:

views:

345

answers:

3

Please help me in understanding how exactly the conversion operators in C++ work? I have a simple example here which I am trying to understand, though it is not very clear how the conversion actually happens by the compiler. Appreciate your time and effort.

Thanks, Light

#include <iostream>

using namespace std;

class Example
{
public:
    Example();
    Example(int val);
    operator unsigned int();
    ~Example(){}
private:
    int itsVal;
};

Example::Example():
itsVal(0)
{}

Example::Example(int val):
itsVal(val)
{}

Example::operator unsigned int ()
{
    return ( itsVal );
}

int main()
{
    int theInt = 5;
    Example exObject = theInt; // here 
    Example ctr(5);
    int theInt1 = ctr; // here
    return 0;
}
+3  A: 
Example exObject = theInt; // implicitly created copy constructor takes place
// object implicitly created from int and then copied
// it is like
Example exObject = Example(theInt);
// so it uses sequence
// Example(int) -> Example(const Example&)
int theInt1 = ctr; // operator int()

If you compiler supports copy constructor optimization and return value optimization you won't notice

Example(const Example&)

execution, but you can declare copy constructor to be private to understand what I am talking about.

Mykola Golubyev
Example(int) is not a copy constructor.
PiotrLegnica
Example(int) is not, but Example example = int is. It uses implicitly created copy constructor, no?
Mykola Golubyev
PiotrLegnica
I think it is just copy constructor optimization.
Mykola Golubyev
Yes, initialization via `T x = (U)y` will create a temporary of `T`, initializing it via `T(U)` ctor, and then initialize `x` via copy constructor from that temporary - except that this step can be optimized away (but check for accessible constructor must still be there).
Pavel Minaev
+2  A: 

You can walk through that code with a debugger (and/or put a breakpoint on each of your constructors and operators) to see which of your constructors and operators is being invoked by which lines.

Because you didn't define them explicitly, the compiler also created a hidden/default copy constructor and assignment operator for your class. You can define these explicitly (as follows) if you want to use a debugger to see where/when they are being called.

Example::Example(const Example& rhs)
: itsVal(rhs.itsVal)
{}

Example& operator=(const Example& rhs)
{
    if (this != &rhs)
    {
        this->itsVal = rhs.itsVal;
    }
    return *this;
}
ChrisW
Do you know how to turn off RVO?
Mykola Golubyev
The following two lines are killing me..Example exObject = theInt;int theInt1 = ctr;Is a copy constructor called in this program and how about the assignment operator. None of them seem to be called.
Zuzu
A: 
Example exObject = theInt; // here

This uses implicit conversion of int to Example, effected by the non-explicit constructor which accepts an int.

This also requires the availability of copy constructor for Example, even though the compiler is allowed to omit copying the instance.

int theInt1 = ctr; // here

This uses implicit conversion of Example to unsigned int, provided by the cast operator.

Cast operators are normally avoided, since they tend to lead to confusing code, and you can mark single-argument constructors explicit, to disable implicit conversions to your class type. C++0x should add also the possibility to mark conversion operators explicit (so you'd need a static_cast to invoke them? - my compiler doesn't support them and all web resources seem to be concentrating on explicit conversion to bool).

UncleBens