Advanced C++ | Conversion Operators

In C++, the programmer abstracts real world objects using classes as concrete types. Sometimes it is required to convert one concrete type to another concrete type or primitive type implicitly. Conversion operators play smart role in such situations.

For example consider the following class

#include <iostream>
#include <cmath>

using namespace std;

class Complex
{
private:
    double real;
    double imag;

public:
    // Default constructor
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i)
    {}

    // magnitude : usual function style
    double mag()
    {
        return getMag();
    }

    // magnitude : conversion operator
    operator double ()
    {
        return getMag();
    }

private:
    // class helper to get magnitude
    double getMag()
    {
        return sqrt(real * real + imag * imag);
    }
};

int main()
{
    // a Complex object
    Complex com(3.0, 4.0);

    // print magnitude
    cout << com.mag() << endl;
    // same can be done like this
    cout << com << endl;
}

We are printing the magnitude of Complex object in two different ways.

Note that usage of such smart (over smart ?) techniques are discouraged. The compiler will have more control in calling an appropriate function based on type, rather than what the programmer expects. It will be good practice to use other techniques like class/object specific member function (or making use of C++ Variant class) to perform such conversions. At some places, for example in making compatible calls with existing C library, these are unavoidable.

— Venki. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.





  • http://hi.csdn.net/space-home.html Simon

    Venki:
    You said,”At some places, for example in making compatible calls with existing C library, these are unavoidable.” would you show a simple example that c used. thanks.

    • http://www.linkedin.com/in/ramanawithu Venki

      @Simon, many of the C style string processing functions accepts “const char *” as input. Consider a hypothetical C++ string class,

       
      class StringHandle
      {
      public:
          // other interfaces
      
          // An interface that returns pointer to
          // underlying character buffer implicitly
          operator const char* ()
          {
              // Delegate call to body
              return pData->rawBuffer();
          }
      
      private:
          // pimpl idiom
          StringBody *pData;
      };
      
      // Usage
      
      int main()
      {
          StringHandle str("A String");
          // ....
      
          char *buf = new char[256];
      
          // An implicit conversion
          ::strcpy(buf, str);
      
          // .....
      
      }
       

      Note that the compiler places call to “operator const char* ()” implicitly to convert String object into raw buffer before making copy using C-style copy function.

      For that matter any implicit conversion to primitive types can be handled in this way.

      For more details refer the book “Advanced C++” by Copelin. Or refer any standard library code like Boost, Qt C++, etc…

  • Venki

    @karan, we will cover C++ variant class in coming posts. Hope Sandeep clarified other question.

    @pajju, Thanks. We would suggest to use such constructs with care when situation demands.

  • karan

    what is Variant class?

  • karan

    The compiler will have more control in calling an appropriate function based on type, rather than what the programmer expects.

    Could you an example, please? An example that shows compiler doing something unexpected.

    • Sandeep

      See http://www.umsl.edu/~subramaniana/overload10.html

      Excerpt from the link

      If enough conversion functions are defined, the ambiguous operations could occur. For example:

       class Angle{
      public:
      	operator float() { return value; }
      	Angle(float f = 0.0) : value(f) {}
      	Angle(Angle& A) : value(A.value) {}
      	friend Angle operator+(const Angle& , const Angle& );
      private:
      	float value;
      };
      
      int main)(){
      	Angle a;
      	float f = 10.0;
      	Angle a1 = a + f;	// Error, ambiguous (float + float) or (Angle + Angle)
      
      	return 0;
      }
       
  • pajju

    This is not smart. You are expecting too much from your Compiler. :)
    (You can expect mail from your lead soon :P)

    • http://www.linkedin.com/in/ramanawithu Venki

      Mail regarding what? It doesn’t matter…

      • pajju

        don’t write such code expecting too much from your compiler.