C++ Casting
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;