Skip to Content
Course content

116: Conversion Operators and explicit

Click on the "Edit" button in the top corner of the screen to edit your slide content.

How do I make my class "act" like another type?

Sometimes you have a class that represents a value—like a Distance object that stores meters—and you want to use it in a mathematical expression without manually calling a getMeters() method every single time. That's where conversion operators come in. You're essentially telling the compiler: "If you ever find yourself needing a double but you've got a Distance object, here is how to turn it into one."

class Distance {
    double meters;
public:
    Distance(double m) : meters(m) {}

    // This is the conversion operator
    operator double() const {
        return meters;
    }
};

// Now this just works
Distance d(10.5);
double total = d + 5.0; // d is implicitly converted to double

Notice that conversion operators don't have a return type. That's because the return type is baked into the name of the operator itself. I'll be honest: they're incredibly convenient, but that convenience is exactly why they can be dangerous.

Wait, why is the compiler converting my object when I didn't ask it to?

This is the "implicit conversion" trap. Because I defined operator double() without any restrictions, the compiler will use it anywhere a double is expected. This sounds great until you realize the compiler will do things you never intended, often leading to bugs that are a nightmare to track down.

Imagine you have a function that calculates the area of a circle using a radius. If you accidentally pass a Distance object into a function expecting a double, it works. But what if you accidentally pass a Distance object into a function expecting a double that represents a percentage? The code compiles, it runs, and it gives you a completely wrong answer without a single warning.

void setTransparency(double alpha) { /* expects 0.0 to 1.0 */ }

Distance dist(500.0); 
setTransparency(dist); // Oops! Compiles perfectly, but sets alpha to 500.0

How does the 'explicit' keyword stop this madness?

Since C++11, you can mark conversion operators as explicit. This tells the compiler: "Do not use this conversion unless I specifically ask for it using a cast." It turns an implicit conversion into an explicit request.

class Distance {
    double meters;
public:
    Distance(double m) : meters(m) {}

    explicit operator double() const {
        return meters;
    }
};

Distance d(10.5);
// double total = d + 5.0; // ERROR: No implicit conversion allowed!
double total = static_cast<double>(d) + 5.0; // SUCCESS: I asked for it.

I almost always recommend using explicit for conversion operators. Yes, it means you have to write static_cast a bit more often, but that's a small price to pay for preventing the compiler from making wild guesses about your intentions. It makes the code much more readable for the next person (or your future self) because the conversion is visible on the screen.




📋 Practical Task

Implementing a Type-Safe Weight Conversion System

You are building a physics engine where weights are stored in a Weight class (representing kilograms). To prevent accidental calculations where weights are mixed up with other floating-point values, you need to implement a safe conversion system.

  • Create a class called Weight that stores a double value.
  • Implement a constructor that initializes the weight.
  • Implement an explicit conversion operator to double.
  • In your main function, create a Weight object.
  • Attempt to pass the Weight object into a function that expects a double without a cast. Confirm that this causes a compiler error.
  • Fix the error by using static_cast<double>() to successfully pass the value.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.