9.9 — Overloading the parenthesis operator

All of the overloaded operators you have seen so far let you define the type of the operator’s parameters, but not the number of parameters (which is fixed based on the type of the operator). For example, operator== always takes two parameters, whereas operator! always takes one. The parenthesis operator (operator()) is a particularly interesting operator in that it allows you to vary both the type AND number of parameters it takes.

There are two things to keep in mind: first, the parenthesis operator must be implemented as a member function. Second, in non-object-oriented C++, the () operator is used to call functions. In the case of classes, operator() is just a normal operator that calls a function (named operator()) like any other overloaded operator.

An example

Let’s take a look at an example that lends itself to overloading this operator:

Matrices are a key component of linear algebra, and are often used to do geometric modeling and 3D computer graphics work. In this case, all you need to recognize is that the Matrix class is a 4 by 4 two-dimensional array of doubles.

In the lesson on overloading the subscript operator, you learned that we could overload operator[] to provide direct access to a private one-dimensional array. However, in this case, we want access to a private two-dimensional array. Because operator[] is limited to a single parameter, it is not sufficient to let us index a two-dimensional array.

However, because the () operator can take as many parameters as we want it to have, we can declare a version of operator() that takes two integer index parameters, and use it to access our two-dimensional array. Here is an example of this:

Now we can declare a Matrix and access its elements like this:

which produces the result:


Now, let’s overload the () operator again, this time in a way that takes no parameters at all:

And here’s our new example:

which produces the result:


Because the () operator is so flexible, it can be tempting to use it for many different purposes. However, this is strongly discouraged, since the () symbol does not really give any indication of what the operator is doing. In our example above, it would be better to have written the erase functionality as a function called clear() or erase(), as matrix.erase() is easier to understand than matrix() (which could do anything!).

Having fun with functors

Operator() is also commonly overloaded to implement functors (or function object), which are classes that operate like functions. The advantage of a functor over a normal function is that functors can store data in member variables (since they are classes).

Here’s a simple functor:

Note that using our Accumulator looks just like making a normal function call, but our Accumulator object is storing an accumulated value.

You may wonder why we couldn’t do the same thing with a normal function and a static local variable to preserve data between function calls. We could, but because functions only have one global instance, we’d be limited to using it for one thing at a time. With functors, we can instantiate as many separate functor objects as we need and use them all simultaneously.


Operator() is sometimes overloaded with two parameters to index multidimensional arrays, or to retrieve a subset of a one dimensional array (with the two parameters defining the subset to return). Anything else is probably better written as a member function with a more descriptive name.

Operator() is also often overloaded to create functors. Although simple functors (such as the example above) are fairly easily understood, functors are typically used in more advanced programming topics, and deserve their own lesson.

Quiz time

1) Write a class that holds a string. Overload operator() to return the substring that starts at the index of the first parameter. The length of the substring should be defined by the second parameter.

Hint: You can use array indices to access individual chars within the std::string
Hint: You can use operator+= to append something to a string

The following code should run:

This should print


Show Solution

9.10 -- Overloading typecasts
9.8 -- Overloading the subscript operator

62 comments to 9.9 — Overloading the parenthesis operator

  • masterOfNothing


    Would it be safer to assert that both starting index and length number cannot be less than 0?

    • It's unlikely that a user of the class passes a negative index, but can still happen. So yes, it's safer.

      - Name your variables descriptively. "i1" and "i2" are meaningless.
      - Pass/return non-fundamental types by reference.
      - Use your editor's auto-formatting feature.
      - Initialize `std::string` with empty curly brackets.

      • masterOfNothing

        In Python you can slice lists (a type of mutable array) with negative numbers as well. So, some people might get tempted to try that in C++.

        Anyway, thank you.

  • Dany

    Hello. Wouldn't it be better to overload our class like that and use the common syntax for two dimensional arrays [][]?

    Also i would like to understand, can i do this for three dimensional array? I tried to write it like that.

    I can't understand why, i thought this should return a pointer to a pointer to an array[4]

    • Atas

      Take a look at this question and the first answer therein:

  • KK

    I am a newbie to C++ and I am thankful for your great tutorials.
    Just wondering why this code is not printing. Only difference to the Alex's code is the in the way I am building the string for return.

    • * Line 20: Initialize your variables with uniform initialization. You used copy initialization.
      * Line 29, 30: Initialize your variables with uniform initialization. You used direct initialization.
      * Line 9, 18: Initialize your variables with uniform initialization.

      In line 21 @temp you're accessing temp[0], which is ok, but you're writing to it, which is not ok. You're then accessing temp[1], temp[2], ..., which produces undefined behavior.

      You need to either append to @temp, or initialize @temp using it's fill constructor.
      Though, fill initializing it is probably unnecessarily slow, since you're overriding it.
      Use @std::string::reserve with @length and then append to it.

  • Hi, Please explain this eratic behaviour of functor. For every new line it is working fine. But when they are called on the same line(separated by tab) then it is eratic:

    Why seemingly same call has different behaviour?

    • Hi Udit!

      The evaluation order of line 24 is undefined. It might produce different output when compiled with another compiler or other settings. If you need a specific order, store the return values of @Accumulate::operator() in temporaries before printing, or do it as you did in lines 18-21.

  • winNi

    I dont understand how c++ differs between Matrix() as a function call and as a new instance of Matrix.

    • If there is a function "Matrix" and a class "Matrix" and you write

      the function will always be preferred. Even if the class has a constructor that takes parameters and the function doesn't and you're calling

      , the class will be ignored and you'll get an error, because the function doesn't take parameters.
      Name your types/variables/functions properly and use uniform initialization and you won't have to worry about this.

  • Hi Alex,

    Is there any way of outputting the results via a GUI such as windows forms? If yes, will this be demonstrated/shown during the tutorials?

    • > Is there any way of outputting the results via a GUI such as windows forms?

      > will this be demonstrated/shown during the tutorials?
      No, the Windows API is terrible and GUI is too big of a topic to be covered. Learncpp is about C++, GUI is OS/DM-specific.
      If all you want to do is output a message you can use @MessageBox from <Windows.h>. The biggest GUI framework is QT, but it's not standard C++.

  • girish

    Hi Alex,
    Wonderful tutorials..Hats off to you..

    This program also prints the same output.So have I coded anything wrong in it, if yes,Could you please brief it?

    • Hi Girish!

      > This program also prints the same output
      Your program doesn't have a length parameter, so this can't be true. Without running it, I'd say your program prints
      rather than the requested

      * Don't use "using namespace", it can cause name collisions.
      * Use uniform initialization

      Since this chapter wasn't about arrays, you don't have to manually construct a string in @operator() like Alex did. Instead of invoking @std::string::string(const char *) like you did, I'd use @std::string::subtr.

      std::string::substr -

  • Jan

    Alex, have you anywhere on this site explained how the "->" operator can be defined and used ? I may missed it somewhere among these pages and if so, my apologies. Thanks !

    • Alex

      I don't have a specific lesson for overloading this operator (as doing so is quite uncommon). I do show an example of doing so in lesson 15.3.

  • Jack

    Quick typo in the comment, the instance is called matrix, not cMatrix

    Also, for the quiz, it may be good to have some kind of length check or assertion to ensure that the substring will not run outside the bounds of the string. As an example, here is mine:

    • Alex

      Typo fixed, thanks for pointing that out!

      Also, yes, bounds checking is a good idea. I've added a line to the quiz per your suggestion. Thanks!


    For the quiz question, would you say that this solution is better than the one above? I'm using substr() instead of a for loop.

    • Alex

      Yes, generally it's better to use well-tested functionality than write your own. For quiz questions, I usually write from scratch because it's better for learning.

  • John Halfyard


    Why don't we have to declare "index1" and "length" as member variables?

  • Livio

    Hello Alex,

    I understand the usage of

    double& Matrix::operator()(int row, int col)
        assert(col >= 0 && col < 4);
        assert(row >= 0 && row < 4);

        return data[row][col];

    in order to retrieve the value of matrix(1, 2) in

        std::cout << matrix(1, 2);  .

    I cannot understand how the assignement works

    matrix(1, 2) = 4.5;  

    Can you help me? I am missing some bit for sure....


    • Alex

      Sure. The function returns a reference, so when we return data[row][col], we're returning a reference to the _actual_ data[row][col], not a copy of data[row][col]'s value. This means the function's return value can be treated just like it were data[row][col] itself -- which means we can assign values to it to update the data.

  • Jeffry

    Hi Alex,   Thanks for always replying so quickly, and for all the work on these pages.  They are great!

    Quick question.   For the quiz why not use std::substr?  Is there a reason you used the for loop instead?

    • Alex

      No particular reason, other than just to show people how things can be done manually. And because I'd be assuming everyone knew what the substr function actually did.

      • Hi Alex!

        Since there are many quizzes about writing functions that are part of the @std library I think it'd be good introduce the according @std functions in the spoiler of the solution, because as it is, there's no way for learners to know that these functions even exist and they'll keep writing them on their own.
        I'll gladly help updating the affected lessons if you want me to.

  • Matt

    My solution for the quiz ended up being the same as yours with only style differences. However, both print out an empty string when the program is executed. Also, there is a missing include for iostream in the suggested solution.

  • dazedbrain

    and includes however many characters are in the second parameter.

    looks like a typo again.

  • Ali

    Hey Alex

    Firstly, thank you so much for these tutorials. These have been an incredible asset to me so far and I'm sure they will act as my primary reference in the future.

    One thing that I noticed is that you have a ";" at the end of the Constructor of your Accumulator class in the snippet of code right above your conclusion. This causes an error.

    I was wondering if you had an idea as to why is this the case?

    All the best. Thank you again for this series of up to date tutorials :-)

  • Anddo

    Hey Alex,

    I'd like clearing something please, about this

    "You may wonder why we couldn’t do the same thing with a normal function and a static local variable to preserve data between function calls. We could, but because functions only have one global instance, we’d be limited to one. With functors, we can instantiate as many separate functor objects as we need."

    "As I understand it, the basic idea of functors is that instead of passing a function pointer to a function to do a specific job, you pass a class with an overloaded () operator to do the same job. The advantage here is that classes can store information about the state of things, whereas functions can not."

    What you meant by "state of things" ? We can use the member functions to store (edit) the class data, can't we ? An example like the above with added member function to achieve same thing.

    • Alex

      I meant that classes can have member variable that can store values, whereas pure functions can not. Because functors are classes, you can add other member functions if you want.

      • Hardik

        One thing I wanted to clarify, that, are function ptrs passed to the function to do a specific job, or the function is actually called, I am a bit doubtful about this.
        Plz explain me this :-
        "You may wonder why we couldn’t do the same thing with a normal function and a static local variable to preserve data between function calls. We could, but because functions only have one global instance, we’d be limited to one. With functors, we can instantiate as many separate functor objects as we need."
        Give an example also, Plz !

        • Alex

          I don't understand your first question.

          For your second question, it's a good exercise for you. Rewrite the accumulator as a normal function that uses a local static to accumulate values. Then try to accumulate two different sets of values with it at the same time. It doesn't work, because you only have one variable accumulating data. It can't differentiate between different sets of values. But a functor can.

  • Peter

    Hi Alex,

    My solution to quiz is

    I was wondering whether using push_back was less efficient than using +?

    • Alex

      It's hard to say without knowing how push_back and operator+= are implemented. Likely they are implemented using the exact same code, so they probably perform the same.

  • Darren

    I've read about functors before but either the explanation was garbled or my brain was switch off. The concise explanation above just makes sense. A functor is a class that has an overloaded operator(), which performs the role of a function call. Neat.

    About the matrix example when you do:

    this, by row major convention, means set the matrix element at row 2, column 3 to 5. With out that convention the code above could mean setting column 2, row 3 to 5. But I guess it should be clear from the function prototype and/or comments as to the convention used.

  • Ola Sh

    Thank you. I was able to overload the subscript operator[] to return a pointer so I could use sequential executions of operator[]. Thanks.

  • Ola Sh

    Hi Alex,

    Well done, another great tutorial. In the first example, we used operator[][] to access elements in data (data[row][col]). I am wondering how the overload operator[][] is implemented in C++, since its definition does not exist according to the Visual Studio compiler. Also, is there a way we can overload or define this operator? Thanks for your help.

    • Alex

      There is no operator[][]. However, if the result of operator[] is the appropriate type, operator[] can be applied to the result. So when we have data[row][col], this is really evaluating as (data[row])[col] (two sequential executions of operator[]).

  • Arash

    Correct this line.

  • tata

    Hi, could someone check if the following comments/interpretations are correct?

    In essence, my question is:

    Do overloaded parenthesis operators rely solely on the presence of a class name to differentiate themselves from a call to a (default) constructor?


  • Janez

    I don't really get what is the "advantage" of overloading () operator, besides the name is shorter than if you would do the same thing with a member function. For other operators it was more logical but I don't get this one (I understand how it works, but not why would someone use it).

    • Colin

      @Janez, in this context its a rather non-idiomatic use. However, when you need to treat a function as a first-class object it can be supremely useful. See the example written up at for a deeper understanding.

      • Nimbok

        This example requires overloading the function call operator (aka parentheses operator) only because boost::apply_visitor happens to invoke the function call operator. This doesn't really illustrate the principle. boost::apply_visitor could just as easily have been implemented to call a function named potato() and accomplish the same thing.

        This seems to demonstrate the benefits more directly:

        The benefit is that it allows for functors - objects that act like functions. E.g.:

        So then, what advantage does a functor have over simply calling an object's member function? E.g.:

        For some explanation of the advantages of functors, see:

  • Whew! It's getting more complicated

  • sunil_s

    In above example cMatrix is a class object and you have not overloaded << operator. still "std::cout << cMatrix(1, 2)" statement is working fine without error. how is it possible??

    • dismas256

      that is possible because the parenthesis operator in that class returns a reference to a built-in datatype "double" which of course has its own overloaded stream extraction operator.

  • bla

    Is there a way to make the overloading of the parenthesis operator work usefully, when dealing with dynamically allocated objects?
    I did the overloading very similar to the way described here and the only way (that I found) to access my object is:


    which looks quite ugly...

    • Alex

      No, you have to dereference the object first, as you suggest -- and since operator() has higher precedence than operator*, you have to put parenthesis around the dereference.

  • sergk

    This concept called "function objects" or "functors".
    Functors in it's essence is C++ style callbacks.

    • sergk

      I must say that functor callbacks is not perfect solution (actually, there is no such thing at all).

      For caller implementation one have to use either known interface - a base class with virtual operator(), or use template.

      • Wikipedia has some more information about functors here, for anybody interested in learning more about them.

        As I understand it, the basic idea of functors is that instead of passing a function pointer to a function to do a specific job, you pass a class with an overloaded () operator to do the same job. The advantage here is that classes can store information about the state of things, whereas functions can not.

        Overloading () for doing functors is an advanced-level C++ concept, so don't sweat it if you're just learning the language. :)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]