Solved

use of function objects

Posted on 2002-06-24
15
195 Views
Last Modified: 2010-04-01
When is it desirable to write a class that overloads operator() instead of using a function?  C
0
Comment
Question by:nke2000
  • 3
  • 2
  • 2
  • +7
15 Comments
 
LVL 3

Expert Comment

by:Crius
Comment Utility
When you want to be able to do something like:

   MyObject num1, num2, num3;

   (do stuff with them)

   num3 = num1 + num2;

instead of:
   MyObject num1, num2, num3;

   (do stuff with them)

   num3.SetValue(num1);
   num3.AddValue(num2);
0
 

Author Comment

by:nke2000
Comment Utility
Crius,
I may be misunderstanding your point, but that looks like an overload of operator+, not of operator().  I don't see how nums1-3 are used as function objects.
0
 
LVL 3

Expert Comment

by:Crius
Comment Utility
Sorry, my mistake. When you said operator(), I though you were referring to operator overloads in general, and didn't specify whether it was operator+, operator=, etc.

From what little I know of operator(), I have only seen it used in templates, but I don't know why or how. Sorry.
0
 
LVL 3

Expert Comment

by:jtm111
Comment Utility
sometimes people want to mimic fortran-style matrix indexes so they might overload () as in:

element(1,3) = 12.0

that's the typical use for me anyway.
0
 
LVL 30

Accepted Solution

by:
Axter earned 100 total points
Comment Utility
There are times when you want to pass a function, that can temporaraly store information while been iterated by another object.  A regular function can't do this adaquately.

Example:
class TestOp
{
public:
     TestOp(int x) : m_x(x){}
     void operator()(int y)
     {
          cout << m_x << " * " << y << " = " << m_x * y << endl;
          ++m_x;
     }
     int m_x;
};

int main(int argc, char* argv[])
{
     int IntArr[5] = {1, 10, 20, 100, 1000};
     for_each(&IntArr[0], &IntArr[5], TestOp(7));

     system("pause");
     return 0;
}
0
 
LVL 22

Expert Comment

by:ambience
Comment Utility
>> When is it desirable to write a class that overloads operator() instead of using a function?

i think its a matter of taste and C++ practice, ofcourse you can equivalently do such situations using global variables and functions, but functors are much more elegant and safer way to do it the C++ way.

couple functors with templates and you have some very powerful C++ language constructs that can save you a lot of time and much safer in terms of strict type-checking.

Also if you are going to use STL (re-usability) you might find the use of functors as inevitable.

Whereas going everything on your own from scratch you can avoid functors at all costs.
0
 
LVL 3

Expert Comment

by:jimbucci
Comment Utility
Providing another example to Crius' example:

A lot of it depends on what your classes can actually do.  For example: say you have a simple string class (textbook example)
class MyString
{
   char string[20];
   MyString operator+( MyString& sString);
... (most code is missing)
}

Now you can easily concatenate strings
MyString s1,s2,s3;

s1 = s2 + s3;  
instead of using strcat().
Stroustrup "The C++ Programming Language" has a good example of a string class.

Sorry for iterating Crius' response.  I would use this operator if I had a class where the objects can be created using combination of two other objects.  But then you can be as creative as you like with these operators based on the complexity your objects.
Also, use of operators makes for cleaner looking code.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 3

Expert Comment

by:Crius
Comment Utility
Thanks jimbucci, but Crius answered the wrong question. :) nke2000 was talking about one particular operator overload, the () one.
0
 
LVL 3

Expert Comment

by:jimbucci
Comment Utility
I stand corrected.  The examples provided clearly show some uses.  I've never overloaded operator(), but I can now see its uses.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Basically it lets you use the name of the object as if it were a function name.  For instance, let's say you have an class named MathOp.  You instantiate two objects of that class:

CMathOp cAdd("+");
CMathOp cSubtract("-");

and later you could use:

    cAdd(1,2);
or
    cSubract(7,3);

Instead of the clumsier:

    cAdd.DoYourOperation(1,2);
    cSubtract.DoYourOperation(7,3);

-- Dan
0
 
LVL 2

Expert Comment

by:Serega
Comment Utility
0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
The obvious answer is anytime you want a class to behave like a function,  the most common *required* usage is when you define class functors for stl algorithms, eg. when you implement your own sorting predicate for std::sort.

Another link with a good example is:

http://www.gotw.ca/gotw/083.htm
0
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
STL Class Functionoid Sort Predicate example:

#include <algorithm>
#include <vector>

using namespace std;

class X
{
public:

    int val;
};

class XSortPredicate
{
public:
    bool operator()(const X& lhs, const X& rhs)
    {
        return lhs.val < rhs.val;
    }
};

void f()
{
    std::vector<X> xvec;
    std::sort(xvec.begin(), xvec.end(), XSortPredicate());
}

BTW, there are significant advantages to using this method of defining predicates than using a function pointer... efficiency being a notable one... the compiler could inline the function object, hence potentially removing *all* function calls from the sort algorithm (hence why std::sort is potentially much more efficient than qsort).
0
 

Author Comment

by:nke2000
Comment Utility
thanks everyone for your help.  Axter's answer is almost identical to Stroustrup.  I was able to step through his code to get a better handle on the problem.
0
 
LVL 1

Expert Comment

by:ramshakal
Comment Utility
>When is it desirable to write a class that overloads operator() instead of using a function

Generally you will find operator() in most of the interfaces of kind Sequence or Iterators.  And its good design pratice to use this operator for interfaces of these kind because it allows internal details hidden from users and thus presenting simplified view of Interface.

Once you design more and more classes and follow  design approach of " outside first (interfaces first) and then  inside (data ). You will automatically find the need of this operator.  You already know how to use this. So here I am giving you a probelm where its desirable to use this operator to simplify things.

class LinkedListIterator;
class LinkedList;
 
 class Node {
   // No public members; this is a "private class"
   friend LinkedListIterator;   // A friend class
   friend LinkedList;
   Node* next_;
   int elem_;
 };
 
 class LinkedListIterator {
 public:
   bool operator== (LinkedListIterator i) const;
   bool operator!= (LinkedListIterator i) const;
   void operator++ ();   // Go to the next element
   int& operator*  ();   // Access the current element
 private:
   LinkedListIterator(Node* p);
   Node* p_;
   friend LinkedList;  // so LinkedList can construct a LinkedListIterator
 };
 
 class LinkedList {
 public:
   void append(int elem);    // Adds elem after the end
   void prepend(int elem);   // Adds elem before the beginning
   // ...
   LinkedListIterator begin();
   LinkedListIterator end();
   // ...
 private:
   Node* first_;
 };

inline void LinkedListIterator::operator++()
 {
   assert(p_ != NULL);  // or if (p_==NULL) throw ...
   p_ = p_->next_;
 }
 
 inline int& LinkedListIterator::operator*()
 {
   assert(p_ != NULL);  // or if (p_==NULL) throw ...
   return p_->elem_;
 }


The key insight is the realization that a LinkedList is not a chain of Nodes. That may be how it is built, but that is not what it is. What it is is a sequence of elements. Therefore the LinkedList abstraction should provide a "LinkedListIterator" class as well, and that "LinkedListIterator" might have an operator++ to go to the next element and operator () to access elements Node Value.

Thanks,
RSV
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now