How To Create Functors and Function Objects |
Written by Mike James | ||||
Monday, 17 June 2024 | ||||
Page 1 of 3 One of the delights of C++ is how often you can discover a new use for something. In this case it is the ability to redefine operators that can be "repurposed" to create function objects or functors. First let's take a look at the problem that functors solve. The code problemObject-oriented programming is currently the best general purpose programming philosophy we have but it has its problems. One of the biggest problems, although rarely expressed clearly, is what to do with the code. Before objects we used pure procedural programming where a big program was broken down into small chunks - called functions, procedures or subroutines depending on your viewpoint. This was generally called top-down or bottom-up modular programming and it was the best we had. Object-oriented programming takes the modular code and puts it where it belongs with the data that is works with. That is objects have properties, i.e. data, and they have methods that work on that data, i.e. methods. This is great but occasionally it seems natural to think about a function as something on its own - something not connected to an object. This a big problem for object-oriented languages and you can find opinion split between allowing standalone functions or demanding that every function belongs to an object. A language that allows functions to stand on their own can't really be called 100% object oriented - unless that is you make stand alone functions objects in their own right. That is you can stick to the "everything is an object" approach and have what look like standalone functions by the simple trick of allowing objects which are functions. In most languages a function object is called either a function object or a first class function but in C++ and a few languages the term functor is also used. The term functor comes from category theory where it is a type of function which maps one category to another homomorphically. Don't worry if you have no idea what all this means - I quote it just to indicate that the use of the term "functor" in connection with function objects is more about intellectual elitism than it is about the accurate use of terminology. As far as C++ and some other language programmers are concerned functor means an object which behaves as a function. Before you take away the idea that function objects are some how very advanced it is worth mentioning that all functions in JavaScript are function objects - although this is a fact that is often overlooked by JavaScript programmers. It is also worth knowing that other languages go to a lot of trouble not to introduce function objects with the same status as other objects. For example, in C# delegates are a way of wrapping a function that belongs to another object. This still doesn't allow you to create stand-alone objects but now you can at least pass a function as if it was an object. Eventually C# had to introduced a standalone function and it did so in the form of a lambda expression which is a standalone function defined on the fly. Interestingly C++0x has also added the lambda expression to the language and this provides another way to construct a standalone function but this time on the fly. Operator overloadingTo return to the idea of functor in C++ we first need to remember how to create a custom operator. First some basic facts - you can only redefine existing operators which keep their precedence and associativity rules. You redefine an operator within a class and the redefinition applies only to that class. That is if you redefine ++ in MyClass then MyObj++ uses the new definition of the operator if and only if MyObj is of type MyClass. Any other input parameter and return value can be of any type you care to define. For a simple example let's redefine ++ to mean increment by 2 rather than 1. First we need to define the class and the overload for the operator: public class MyClass int operator ++ () Notice that the return type is int. It is more usual for the return type to be the same type as the object the operator acts on. Now that we have the definition of the class we can try it out: MyClass MyObj1; You will discover that result holds 3 as it should. If you want to redefine a binary operator simply add a parameter in the operator definition e.g. int operator + (int y) Notice that you can't change the arity of an operator - if the operator is binary it has to be redefined as a binary operator. |
||||
Last Updated ( Monday, 17 June 2024 ) |