kenics.net

Technical notes on perl, python, php, sql, cgi, c/c++, q/kdb+, unix/shell, revision control tools, data structures & algorithms, and their applications into web services and other various forms of software engineering.

C++ operator overload & function object functor

 
(ref) 
http://www.geocities.jp/ky_webid/cpp/language/017.html 
 
################################# 
####    operator overload    #### 
################################# 
 
a very useful and powerful feature of C++. 
 
you can overload operator in C++. (pretty much everything as below) 
 
 +       -       *       /       %       ^       &       | 
 ~       !       ,       =       = 
 ++      --      <<      >>      ==      !=      &&      || 
 +=      -=      /=      %=      ^=      & =     |=      *= 
 <<=     >>=     [ ]     ( )     ->      ->*     new     delete 
 
e.g. 
<< >> are supposed to be bit shift but in case of std::cout and std::cin those operators are overloaded. 
 
####  overload forbidden operators (below 6 are not allowed) 
 
?: :: . .* sizeof typeid 
 
 
below code taken from http://tinyurl.com/yns7vg  and modified a bit. 
 
-------------------- point.h  --------------------- 
class CPoint 

public: 
CPoint(): m_x(0), m_y(0){} 
CPoint(int x, int y); 
 
CPoint  operator+(const CPoint& obj);  // +   overload 
CPoint& operator+=(const CPoint& obj); // +=  overlaod 
 
void set(int x, int y); 
int getx(void){ return m_x; } 
int gety(void){ return m_y; } 
 
private: 
int m_x; 
int m_y; 
}; 
--------------------------------------------------- 
 
--------------------  point.cpp -------------------- 
#include "point.h" 
 
CPoint::CPoint(int x, int y) 

set( x, y ); 

 
 
void CPoint::set(int x, int y) 

this->m_x = x;          // "this->"  is optional 
this->m_y = y;          // but you will need it when variables have the same name like  x = x 

 
CPoint CPoint::operator+(const CPoint& obj) 

CPoint tmp; 
tmp.m_x = m_x + obj.m_x; 
tmp.m_y = m_y + obj.m_y; 
return tmp; 

 
CPoint& CPoint::operator+=(const CPoint& obj)  // return type can be just CPoint 

m_x += obj.m_x; 
m_y += obj.m_y; 
return *this; 

----------------------------------------------------- 
------------------  main.cpp  -------------------- 
#include "point.h" 
#include <iostream> 
 
int main() 

CPoint point1( 100, 150 ); 
CPoint point2( 200, 10 ); 
CPoint point3( 5, 5); 
 
point1 = point2 + point3;                 // this will now nicely translate to below. 
 
    // or 
    // point1 = point2.operator+(point3);    // same as above 
 
    // or 
// point1.m_x = point2.m_x + point3.m_x   // this you cannot do as m_x,m_y are private 
// point1.m_y = point2.m_y + point3.m_y 
 
 
point1 += point2;          // similarly 
 
//or 
// point1 = point1.operator+=(point2); 
 
    cout << point1.getx() << ' ' << point1.gety() << endl;    // 405 25 
 
return 0; 

-------------------------------------------------- 
 
========> lets analyze the overload func def. 
 
CPoint CPoint::operator+(const CPoint& obj) 
 
// return type CPoint makes sense as we want to assign the addition of two CPoint objects into a new one. 
// input param is a "reference" to CPoint. this is not a must. but think about two other alternatives. 
 
(1) pointer 
 
if you use a pointer for the input param, the definition will look like below. 
------------------------------------------- 
CPoint CPoint::operator+(const CPoint* obj) 

        CPoint tmp; 
        tmp.m_x = m_x + obj->m_x; 
        tmp.m_y = m_y + obj->m_y; 
        return tmp; 

------------------------------------------- 
 
but the prob is this means you have to use it as below 
 
point1 = point2 + &point3;   // messy 
 
 
(2) by copy 
 
just remove the ampersand &.  this will work but is not efficient as we copy the entire input object into obj, which may include other heavy member variables. 
 
------------------------------------------- 
CPoint CPoint::operator+(const CPoint obj) 

        CPoint tmp; 
        tmp.m_x = m_x + obj.m_x; 
        tmp.m_y = m_y + obj.m_y; 
        return tmp; 

------------------------------------------- 
 
point1 = point2 + point3; 
 
 
 
############################# 
#####    this  pointer    ### 
############################# 
 
"this" is a pointer to the class itself which can be called within the class's member functions. often, you dont have to explicitly call it but if you have variables of the same name with diff scopes, then "this" can let you distinguish. 
 
 
 
################################################## 
###    a technique to prevent instance copy    ### 
################################################## 
 
make the operations private as below. 
 
---------------------------------------- 
class CParent 

 public: 
CParent(){}   // constructor 
~CParent(){}  // desctructor 
 private: 
CParent(const CParent&);              // copy constructor 
CParent operator=(const CParent&);    // = operator overload 

---------------------------------------- 
 
 
 
 
######################################### 
###   Function Object (aka functor)   ###     #include <functional> 
######################################### 
 
a function object = a class that overloads operator(). 
 
as per below examples, a functor is very useful and can replace an ordinary function in many places in C++. 
 
--------------- 
int main() 

  plus<int> pl; 
  int result = pl(3,4);    // see how we can use it like a normal function 
  cout << result;          // 7 

--------------- 
-----------------------------------------------------------// "plus" class definition 
template <class T> struct plus { 
  T operator() (const T& x, const T& y) const {return x+y;} 
}; 
----------------------------------------------------------- 
 
 
a more in-practice use case of a functor is in place of a callback func, as below. 
 
---------------------------------------------------------------  // fctr.cpp 
#include <iostream> 
 
class compare_class { 
public: 
  bool operator()(int A, int B) const { 
    return (A > B); 
  } 
}; 
 
// C++ sort_ints definition 
template <typename ComparisonFunctor> 
void sort_ints(int* arr, int arrSize, ComparisonFunctor comp){ 
  int i; 
  int j; 
  // a plain bubble sort 
  for (i = 0; i< arrSize ; i++) 
    for(j = 0; j < arrSize-i-1 ;j++){ 
      if (comp(arr[j],arr[j+1])){       // see the use of functor here. again, it is just like a callback function. 
          arr[j]   = arr[j] + arr[j+1]; 
          arr[j+1] = arr[j] - arr[j+1]; 
          arr[j]   = arr[j] - arr[j+1]; 
        } 
    } 

 
int main() { 
  int items[] = {4, 3, 1, 2}; 
  int arrSize = sizeof(items) / sizeof(int); 
  //  compare_class functor; 
  //  sort_ints(items, arrSize, functor); 
  sort_ints(items, arrSize, compare_class());   // this simply works 
  for (int i = 0; i < arrSize ;i++) 
    std::cout << items[i];                      // prints 1 2 3 4 

-------------------------------------------------------------- 
 
===> so as you can see, the benefit of functor is you can use it as a callback function where you have access to the object's property (data, functions). this is different cos in C, you had to pass in a pointer to a function which couldnt access the data from caller function. 
 
functor can be used in non-callback code. 
e.g. 
------------------------- 
  functor_class Y; 
  int result = Y( a, b ); 
------------------------- 
 
 
## 6 maths function objects(functors) 
plus<type>, minus<type>, negate<type> // change +- 
multiplies<type>, divides<type>, modulus<type> // like % 
 
## 6 relational ops function objects 
less<type>, less_equal<type>, greater<type>, greater_equal<type>, equal_to<type>, not_euqal_to<type> 
 
## 3 logical ops function objects 
logical_and<type>, logical_or<type>, logical_not<type>   //  &&, ||, ! respectively 
 
-----------------------------------// usage example 
 
binary_search( vec.begin(), vec.end(), elem, greater<int>() );   // tells ascending order search 
transform( vec.begin(), vec.end(), vec2.begin(), vec3.begin(), plus<int>() );  // adds vec & vec2 onto vec3 
transform( vec.begin(), vec.end(), vec2.begin(), vec2.end(), multiplies<int>() );  //multiply and update vec 
 
 
### 
### functor adapater 
### 
 
(ref) 
http://stackoverflow.com/questions/2218889/c-functor-to-output-iterator-adapter 
 
------------------------------------------------------------------ 
 
vector<int> vec; 
int val; 
vector<int>::const_iterator iter = vec.begin(); 
while ( (iter = find_if ( iter , vec.end(), bind2nd( less<int>, val ))) != vec.end()) 

        cout << *iter << " is less than " << val << '\n'; 
        iter++; 

// find cannot accept function objects. 
// bind2nd ( less<int>, val )   will use val as the 2nd input param and compare with each *iter 
// bind1st ( less<int>, val )   will use val as the 1st input param and compare with each *iter 
 
std::not1()  // used to negate the result of unary function objects like equal_to<type> 
std::not2()  // used to negate the result of binary function objects like less<type> 
 
-----------------------------------------------------------------

  1. 2014-05-08 01:31:57 |
  2. Category : cpp
  3. Page View:

Google Ads