Monday, 20 February 2012

Operator Overloading in C++ Part 3

In the previous post we looked at the mandated member operators, for this part I'm going to look at the different types of operators we can generate and provide examples of each.

For ease I will split this section into relational operators and arithmetic operators. We can represent the relational operators using the following diagram


These operators will always return a boolean value which will be the result of some form of comparison. 


Arithmetic operators will return an object of some type which depending upon the context may be either the same object or a new type of object.  Later we will also add the += style operators which will mutate the current object rather than returning a value.
Equality Operators
In the case of the Vec3 class there are only two equality operator which make sense to implement, these are the == and != operators. Also we must ensure that we are doing correct comparison as we are storing floating point values. ( see here for an in depth discussion of floating point comparison ). For this example I'm going to generate a very simple FCompare macro which will be used to do a comparison via a simple epsilon error value.


//----------------------------------------------------------------------------------------------------------------------
/// @brief define EPSILON for floating point comparison
//----------------------------------------------------------------------------------------------------------------------
#ifndef EPSILON
  const float EPSILON = 0.001f;
#endif

//----------------------------------------------------------------------------------------------------------------------
/// @brief FCompare macro used for floating point comparison functions
//----------------------------------------------------------------------------------------------------------------------
  #define FCompare(a,b) \
      ( ((a)-EPSILON)<(b) && ((a)+EPSILON)>(b) )
In the first example I will produce a "Member operator" for the equality operator, first in the .h file we declare the operator
bool Vec3::operator==(const Vec3 &_rhs)
{
  return FCompare(m_x,_rhs.m_x) &&
         FCompare(m_y,_rhs.m_y) &&
         FCompare(m_z,_rhs.m_z);
}
As you can see in this case we do a component wise FCompare with the current object and the rhs value. We can test this using the following code from the previous examples
if(b==c)
 std::cout<<"b==c is true\n";
else
 std::cout<<"b!=c \n";
if(a==fromFloat)
 std::cout<<"a==fromFloat\n";
else
 std::cout<<"a!=fromFloat\n";
Which gives the following output
testing equality operators 
b==c is true
a!=fromFloat
To generate the != method we do the following

/// in .h
/// @brief != operator
bool operator!=(const Vec3 &_rhs);
/// in .cpp
bool Vec3::operator!=(const Vec3 &_rhs)
{
  return !(*this==_rhs);
}
For the free function operator we have to write some additional code again to allow the free function access to the attributes. In this case we are going to write a method called isEqual ( note that my coding standard says this kind of method should be formed as a question as it returns a bool)
/// @brief function to test equality
bool isEqual(const Vec3 &_rhs) const;
The actual code for this class method will use the same FCompare macro as above and looks like this
bool Vec3::isEqual(const Vec3 &_rhs) const
{
  return FCompare(m_x,_rhs.m_x) &&
         FCompare(m_y,_rhs.m_y) &&
         FCompare(m_z,_rhs.m_z);
}
The free function definitions of the == and != methods are now declared outside of the class but still in the .h file as follows
/// @brief free operator for equality testing
bool operator ==(const Vec3 &_lhs, const Vec3 &_rhs);
/// @brief free operator for equality testing
bool operator !=(const Vec3 &_lhs, const Vec3 &_rhs);
Finally we write the main function code, not that as they are no longer class methods it is no longer valid to mark the methods as const (in fact you get the following error with g++ error: non-member function 'bool operator==(const Vec3&, const Vec3&)' cannot have cv-qualifier )
bool operator ==(const Vec3 &_lhs, const Vec3 &_rhs) const
{
  return _lhs.isEqual(_rhs);
}

bool operator !=(const Vec3 &_lhs, const Vec3 &_rhs)
{
  return !_lhs.isEqual(_rhs);
}

1 comment:

  1. Thanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information. Python Training in Chennai

    ReplyDelete