C++ Casting

CPP

Implicit conversion in C++ is when one type is converted to another without the need of a special operator. It looks automatic. When dealing with standard or built-in types, the compiler attempts conversions until it succeeds (with or without warnings) or fails (errors out).

When dealing with custom C++ Constructs, the programmer will need to define member functions to allow implicit conversion. Take the two data structures below. We have a struct called Quartet that is some generic container for 4 floats and a potentially meatier class called Rect.

// Tuple of 4 float values
struct Quartet { float a, b, c, d; };

// Blueprint for a Rectangle
class Rect
{
public:
    //etc etc
    float xUpperLeft, yUpperLeft;
    float xLowerRight, yLowerRight;
    float Area()
    {
        return 2 * ( (xLowerRight - xUpperLeft) + (yUpperLeft - yLowerRight) );
    }
    //etc etc
};

There are a few ways to enable implicit conversion.

Cast Operator

This will allow us to enable implicit conversion ‘‘to’’ another type.

class Rect
{
public:
    //etc etc
    operator Quartet()
    {
        Quartet q = Quartet();
        q.a = xUpperLeft; q.b = yUpperLeft; 
        q.c = xLowerRight; q.d = yLowerRight;
        return q;
    }
};

The method above could also just do return Quartet() and some other code could exist to define how values are set.

//Usage
Rect myRect;
Quartet myQuartet = myRect;

This is the use case where we’ve made a new Quartet using myRect’s values.

Assignment Operator

This will allow us to enable implicit conversion ‘‘from’’ another type but only via assignment.

// Blueprint for a Rectangle
class Rect
{
public:
    //etc etc
     Rect& operator= (const Quartet& q)
    {
        // xUpperLeft = q.a; etc etc
        return *this;
    }
};

Above, the assignment operator of Rect is set to be able to take in a Quartet constant reference, do some processing and return itself as a reference. Below is how you would use it.

Rect myRect;
Quartet myQuartet;
myRect = myQuartet;

With this method, you will not be able to construct/assign Rect in one expression i.e. Rect myRect = myQuartet will not compile. For that you will need:

Type Constructor

Another way to get implicit conversion ‘‘from’’ another type is to simply have a constructor with a single argument of that type.

class Rect
{
public:
    //etc etc    
    Rect(const Quartet& q)
    {
        // Initialize values here
    }
};

In the constructor, you can set Rect’s values with the incoming Quartet. The use case can only happen when you construct your Rect so it’s a little more rigid.

Quartet myQuartet;
Rect myRect = myQuartet;