9.10 — Overloading typecasts

In the lesson 4.4 -- Type conversion and casting, you learned that C++ allows you to convert one data type to another. The following example shows an int being converted into a double:

C++ already knows how to convert between the built-in data types. However, it does not know how to convert any of our user-defined classes. That’s where overloading the typecast operators comes into play.

Overloading the typecast operators allows us to convert our class into another data type. Take a look at the following class:

This class is pretty simple: it holds some number of cents as an integer, and provides access functions to get and set the number of cents. It also provides a constructor for converting an int into a Cents.

If we can convert an int into a Cents, then doesn’t it also make sense for us to be able to convert a Cents back into an int? In some cases, this might not be true, but in this case, it does make sense.

In the following example, we have to use getCents() to convert our Cents variable back into an integer so we can print it using printInt():

If we have already written a lot of functions that take integers as parameters, our code will be littered with calls to getCents(), which makes it more messy than it needs to be.

To make things easier, we can overload the int typecast, which will allow us to cast our Cents class directly into an int. The following example shows how this is done:

There are two things to note:

  1. To overload the function that casts our class to an int, we write a new function in our class called operator int(). Note that there is a space between the word operator and the type we are casting to.
  2. Casting operators do not have a return type. C++ assumes you will be returning the correct type.

Now in our example, we can call printInt() like this:

The compiler will first note that function printInt takes an integer parameter. Then it will note that variable cents is not an int. Finally, it will look to see if we’ve provided a way to convert a Cents into an int. Since we have, it will call our operator int() function, which returns an int, and the returned int will be passed to printInt().

We can now also explicitly cast our Cents variable to an int:

You can overload cast operators for any data type you wish, including your own user-defined data types!

Here’s a new class called Dollars that provides an overloaded Cents cast operator:

This allows us to convert a Dollars object directly into a Cents object! This allows you to do something like this:

Consequently, this program will print the value:


which makes sense, since 9 dollars is 900 cents!

9.11 -- The copy constructor
9.9 -- Overloading the parenthesis operator

24 comments to 9.10 — Overloading typecasts

  • Deepak

    Can somebody please tell me how to overload standard datatype like float to user defined datatype. I have function f2my(float f, mttype* m) which converts float to mytype. I want to overload all floats in my code with mytype i.e. ‘float a’ should be ‘mytype a’.

    Thank you.

  • Matt

    In the code snippet above the first Dollar class code example, you wrote:
    "We can now also explicitly cast our Cents variable to an int:
    Cents cents(7);
    int cents = static_cast<int>(cents);"

    How can you have two identifiers of the same name, but of two different types? Did you mean to use a different identifier for the int variable?

  • Christos

    Hi Alex,

    What if we not only have int dollars/cents but also double? For example dollars(9) or dollars(9.3)

    • Alex

      If this is a valid use case, then the Dollars class would need to modified to handle fractional dollars.

      At the end of this chapter, there’s a quiz question around implementing fixed point numbers that would be a good way to handle this (it’s not quite as easy as it seems).

  • Sourabh S. Rawat

    We have overloade typecast to int here, so cents get converted to int. But , what if we have also overloaded << operator for the Cents class??
    I tried it and it looks like overloaded << was used.

    • Alex

      An overloaded operator<< for class Cents is considered a better match than an implicit conversion to integer, so the overloaded operator<< will be used. Of course, if we'd overloaded operator<<, there wouldn't much point in even having a printCents() function.

  • Peter

    Hi Alex,

    letting you know that there is a typo

    should be

    this happens in the 2nd and 3rd instance of your Cents class code

  • Hunter

    Hi Alex:
    In the last example above,why can’t

    pass value by reference like this?

    • Alex

      The implicit conversion from Dollars to Cents creates a temporary (anonymous) Cents object. In the case where the function parameter is passed by value, this anonymous Cents object is copied into the Cents parameter. However, non-const references aren’t allowed to be assigned to anonymous objects, so in the case where the function parameter is a reference, the conversion can’t happen.

      Since printCents doesn’t modify the parameter, a better thing to do would be to make printCents take a const reference (which can be bound to a temporary object). However, our conversion to int() won’t work in this case, because it’s not flagged as const, so we’d need to modify the overloaded int cast to be const (which we probably should have done anyway).

  • Ola Sh

    Thanks for your help.

  • Ola Sh

    Hi Alex,

    I would like to know if you can overload a typecast operator to convert a Cents object to a std::string object. I tried to overload the operator, but Visual Studio points out that no operator exists for converting int to strings. Can I define or overload an operator to convert from integers to strings? Thanks for your help.

    • Alex

      You can definitely overload a typecast to convert your class to a string. The challenge you’re running into here isn’t that, but rather figuring out how to convert an integer to a std::string in the first place. Prior to C++11, this isn’t easy. But in C++11, you can use the std::to_string() function:

      That said, if your goal is just to print the state of something, you’re better off overloading operator>>.

  • Steiner

    Hello Alex,

    I tried to expand your code and it gave me errors that I don’t even understand on how to solve it using the lessons learned on this chapter.

    this gives out a compiler error of:
    #1. "error: expected type-specifier before ‘Meters’
             operator Meters() { return Meters(m_unit * 1000); }"


    #2. "error: could not convert ‘value2’ from ‘Millimeters’ to ‘Meters’

    I thought of solving error #1 would be by doing a forward declaration of "class Meters" (as shown in the commented code).
    After doing that, the compiler showed a new kind of error:
    "error: return type ‘class Meters’ is incomplete
             operator Meters() { return Meters(m_unit * 1000); }"

    which doesn’t seem to mean anything. It might be the compiler doesn’t have a complete idea about the "class Meters" for it to be a return type?

    The #2 error is very odd since the call "PrintMillimeters(value1);" worked (didn’t give any compiler errors) which is expected to call in the operator() to do a Meters to Millimeters conversion.

    But the other way around, the call "PrintMeters(value2);" gave a compiler error as written above in #2.

    Thank you again for this tutorials.

    • Alex

      The problem is that you have a circular dependency here. Meters depends on knowing the declaration of Millimeters, and Millimeters depends on knowing the declaration of Meters.

      The best solution is to move each class into its own header file, and move the function implementations into a .cpp file.

      That way each class can see the declaration of the other, and the classes will be fully declared before the function definitions are compiled.

      • Steiner

        Hello Alex,

        Thank you for your time.

        Unfortunately, I’m still having the same compilation problems even after I did your proposed solution and checking online for other solutions :(. I made sure I included the Header Guards, placed the function implementations into their respective .cpp files, and use the #include directive to include the necessary header files in each of the .cpp file. Here’s the complete separated code:






        The compilation problem (codeblocks, g++ 4.9.2) still says:
        1. Meters.h|18|error: expected type-specifier before ‘Millimeters’
        2. main.cpp|33|error: could not convert ‘value1’ from ‘Meters’ to ‘Millimeters’

        Just answer this question whenever you can and sorry for taking your time. I’m on 10.4 container classes now and I’m really learning a lot. I’m also making sure to read most if not all the discussions found at the end of the chapters :). So, Thank you for the lessons!

        • Alex

          The problem is that Millimeters.h is including Meters.h, which includes Millimeters.h -- essentially a circular reference. Due to the header guards on Millimeters.h, when Meters.h includes Millimeters.h, the header file doesn’t get included, so Meters.h doesn’t see the declaration for Millimeters.h.

          Fortunately, in this case there’s an easy fix. Instead of having each header #include the other, replace the #includes with forward declarations for the other class. For example, at the top of Millimeters.h, replace #include “Meters.h” with “class Meters;” And do vice-versa for Meters.h.

          That way, the overloaded typecast in the header will know that Meters and Millimeters are types, so it will compile.

          Make sense?

          • Steiner

            I think I get it now. I thought that this is the sequence that the compiler does:

            processing the file Millimeters.h (goes through Millimeters.h to Meters.h then back to Millimeters.h)
            -MILLIMETERS_H gets defined
            -include "Meters.h"
            -goes inside Meters.h file
            -sees #include "Millimeters.h"
            -goes inside Millimeters.h
            -ignores this file since MILLIMETERS_H was already defined and skips this header file (due to #ifndef)
            -goes back to Meters.h file
            -proceeds on the class definition of class Meters

            Which prevents circular reference.

            However I forgot to add in how the compiler processes the other file as well.

            Now when processing the file Meters.h (goes through Meters.h to Millimeters.h then back to Meters.h) and as you said, due to the header guards on Millimeters.h
            -METERS_H was already defined so this file doesn’t get processed
            -so Meters.h doesn’t see the declaration for Millimeters.h

            Thank you Alex, I did the replacement and made the program run. I learned a lot from you :D.

  • Brooklyn

  • Zafer

    To convert a Dollar object to a Cents object, Dollar class uses Cents class by returning Cents(m_nDollars * 100). Shouldn’t we declare the Cents class before Dollar to be able to generate a Cents object?

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter