21.9 — Overloading the subscript operator

Now, whenever we use the subscript operator ([]) on an object of our class, the compiler will return the corresponding element from the m_list member variable! This allows us to both get and set values of m_list directly.

Detecting index validity

Make sure you’re not trying to call an overloaded operator[] on a pointer to an object.

  • Sign In / Suggest an Article

Current ISO C++ status

Upcoming ISO C++ meetings

Upcoming C++ conferences

Compiler conformance status

CppCon 2024

September 15-20, Aurora, CO, USA

Meeting C++ 2024

November 14-16, Berlin, Germany

operator overloading

Operator overloading, what’s the deal with operator overloading.

It allows you to provide an intuitive interface to users of your class, plus makes it possible for templates to work equally well with classes and built-in/intrinsic types.

Operator overloading allows C/C++ operators to have user-defined meanings on user-defined types (classes). Overloaded operators are syntactic sugar for function calls:

What are the benefits of operator overloading?

By overloading standard operators on a class, you can exploit the intuition of the users of that class. This lets users program in the language of the problem domain rather than in the language of the machine.

The ultimate goal is to reduce both the learning curve and the defect rate.

What are some examples of operator overloading?

Here are a few of the many examples of operator overloading:

  • myString + yourString might concatenate two std::string objects
  • myDate++ might increment a Date object
  • a * b might multiply two Number objects
  • a[i] might access an element of an Array object
  • x = *p might dereference a “smart pointer” that “points” to a disk record — it could seek to the location on disk where p “points” and return the appropriate record into x

But operator overloading makes my class look ugly; isn’t it supposed to make my code clearer?

Operator overloading makes life easier for the users of a class , not for the developer of the class!

Consider the following example.

Some people don’t like the keyword operator or the somewhat funny syntax that goes with it in the body of the class itself. But the operator overloading syntax isn’t supposed to make life easier for the developer of a class. It’s supposed to make life easier for the users of the class:

Remember: in a reuse-oriented world, there will usually be many people who use your class, but there is only one person who builds it (yourself); therefore you should do things that favor the many rather than the few.

What operators can/cannot be overloaded?

Most can be overloaded. The only C operators that can’t be are . and ?: (and sizeof , which is technically an operator). C++ adds a few of its own operators, most of which can be overloaded except :: and .* .

Here’s an example of the subscript operator (it returns a reference). First with out operator overloading:

Now the same logic is presented with operator overloading:

Why can’t I overload . (dot), :: , sizeof , etc.?

Most operators can be overloaded by a programmer. The exceptions are

There is no fundamental reason to disallow overloading of ?: . So far the committee just hasn’t seen the need to introduce the special case of overloading a ternary operator. Note that a function overloading expr1?expr2:expr3 would not be able to guarantee that only one of expr2 and expr3 was executed.

sizeof cannot be overloaded because built-in operations, such as incrementing a pointer into an array implicitly depends on it. Consider:

Thus, sizeof(X) could not be given a new and different meaning by the programmer without violating basic language rules.

What about :: ? In N::m neither N nor m are expressions with values; N and m are names known to the compiler and :: performs a (compile time) scope resolution rather than an expression evaluation. One could imagine allowing overloading of x::y where x is an object rather than a namespace or a class, but that would – contrary to first appearances – involve introducing new syntax (to allow expr::expr ). It is not obvious what benefits such a complication would bring.

operator. (dot) could in principle be overloaded using the same technique as used for -> . However, doing so can lead to questions about whether an operation is meant for the object overloading . or an object referred to by . . For example:

This problem can be solved in several ways. So far in standardization, it has not been obvious which way would be best. For more details, see D&E .

Can I define my own operators?

Sorry, no. The possibility has been considered several times, but each time it was decided that the likely problems outweighed the likely benefits.

It’s not a language-technical problem. Even when Stroustrup first considered it in 1983, he knew how it could be implemented. However, the experience has been that when we go beyond the most trivial examples people seem to have subtly different opinions of “the obvious” meaning of uses of an operator. A classical example is a**b**c . Assume that ** has been made to mean exponentiation. Now should a**b**c mean (a**b)**c or a**(b**c) ? Experts have thought the answer was obvious and their friends agreed – and then found that they didn’t agree on which resolution was the obvious one. Such problems seem prone to lead to subtle bugs.

Can I overload operator== so it lets me compare two char[] using a string comparison?

No: at least one operand of any overloaded operator must be of some user-defined type (most of the time that means a class ).

But even if C++ allowed you to do this, which it doesn’t, you wouldn’t want to do it anyway since you really should be using a std::string -like class rather than an array of char in the first place since arrays are evil .

Can I create a operator** for “to-the-power-of” operations?

The names of, precedence of, associativity of, and arity of operators is fixed by the language. There is no operator** in C++, so you cannot create one for a class type.

If you’re in doubt, consider that x ** y is the same as x * (*y) (in other words, the compiler assumes y is a pointer). Besides, operator overloading is just syntactic sugar for function calls. Although this particular syntactic sugar can be very sweet, it doesn’t add anything fundamental. I suggest you overload pow(base,exponent) (a double precision version is in <cmath> ).

By the way, operator^ can work for to-the-power-of, except it has the wrong precedence and associativity.

The previous FAQs tell me which operators I can override; but which operators should I override?

Bottom line: don’t confuse your users.

Remember the purpose of operator overloading: to reduce the cost and defect rate in code that uses your class. If you create operators that confuse your users (because they’re cool, because they make the code faster, because you need to prove to yourself that you can do it; doesn’t really matter why), you’ve violated the whole reason for using operator overloading in the first place.

What are some guidelines / “rules of thumb” for overloading operators?

Here are a few guidelines / rules of thumb (but be sure to read the previous FAQ before reading this list):

  • Use common sense. If your overloaded operator makes life easier and safer for your users, do it; otherwise don’t. This is the most important guideline. In fact it is, in a very real sense, the only guideline; the rest are just special cases.
  • If you define arithmetic operators, maintain the usual arithmetic identities. For example, if your class defines x + y and x - y , then x + y - y ought to return an object that is behaviorally equivalent to x . The term behaviorally equivalent is defined in the bullet on x == y below, but simply put, it means the two objects should ideally act like they have the same state. This should be true even if you decide not to define an == operator for objects of your class.
  • You should provide arithmetic operators only when they make logical sense to users. Subtracting two dates makes sense, logically returning the duration between those dates, so you might want to allow date1 - date2 for objects of your Date class (provided you have a reasonable class/type to represent the duration between two Date objects). However adding two dates makes no sense: what does it mean to add July 4, 1776 to June 5, 1959? Similarly it makes no sense to multiply or divide dates, so you should not define any of those operators.
  • You should provide mixed-mode arithmetic operators only when they make logical sense to users. For example, it makes sense to add a duration (say 35 days) to a date (say July 4, 1776), so you might define date + duration to return a Date . Similarly date - duration could also return a Date . But duration - date does not make sense at the conceptual level (what does it mean to subtract July 4, 1776 from 35 days?) so you should not define that operator.
  • If you provide constructive operators, they should return their result by value. For example, x + y should return its result by value. If it returns by reference, you will probably run into lots of problems figuring out who owns the referent and when the referent will get destructed. Doesn’t matter if returning by reference is more efficient; it is probably wrong . See the next bullet for more on this point.
  • If you provide constructive operators, they should not change their operands. For example, x + y should not change x . For some crazy reason, programmers often define x + y to be logically the same as x += y because the latter is faster. But remember, your users expect x + y to make a copy. In fact they selected the + operator (over, say, the += operator) precisely because they wanted a copy. If they wanted to modify x , they would have used whatever is equivalent to x += y instead. Don’t make semantic decisions for your users; it’s their decision, not yours, whether they want the semantics of x + y vs. x += y . Tell them that one is faster if you want, but then step back and let them make the final decision — they know what they’re trying to achieve and you do not.
  • If you provide constructive operators, they should allow promotion of the left-hand operand (at least in the case where the class has a single-parameter ctor that is not marked with the explicit keyword ). For example, if your class Fraction supports promotion from int to Fraction (via the non- explicit ctor Fraction::Fraction(int) ), and if you allow x - y for two Fraction objects, you should also allow 42 - y . In practice that simply means that your operator-() should not be a member function of Fraction . Typically you will make it a friend , if for no other reason than to force it into the public: part of the class , but even if it is not a friend, it should not be a member.
  • In general, your operator should change its operand(s) if and only if the operands get changed when you apply the same operator to intrinsic types. x == y and x << y should not change either operand; x *= y and x <<= y should (but only the left-hand operand).
  • If you define x++ and ++x , maintain the usual identities. For example, x++ and ++x should have the same observable effect on x , and should differ only in what they return. ++x should return x by reference; x++ should either return a copy (by value) of the original state of x or should have a void return-type. You’re usually better off returning a copy of the original state of x by value, especially if your class will be used in generic algorithms. The easy way to do that is to implement x++ using three lines: make a local copy of *this , call ++x (i.e., this->operator++() ), then return the local copy. Similar comments for x-- and --x .
  • If you define ++x and x += 1 , maintain the usual identities. For example, these expressions should have the same observable behavior, including the same result. Among other things, that means your += operator should return x by reference. Similar comments for --x and x -= 1 .
  • If you define *p and p[0] for pointer-like objects, maintain the usual identities. For example, these two expressions should have the same result and neither should change p .
  • If you define p[i] and *(p+i) for pointer-like objects, maintain the usual identities. For example, these two expressions should have the same result and neither should change p . Similar comments for p[-i] and *(p-i) .
  • Subscript operators generally come in pairs; see on const -overloading .
  • If you define x == y , then x == y should be true if and only if the two objects are behaviorally equivalent. In this bullet, the term “behaviorally equivalent” means the observable behavior of any operation or sequence of operations applied to x will be the same as when applied to y . The term “operation” means methods, friends, operators, or just about anything else you can do with these objects (except, of course, the address-of operator). You won’t always be able to achieve that goal, but you ought to get close, and you ought to document any variances (other than the address-of operator).
  • If you define x == y and x = y , maintain the usual identities. For example, after an assignment, the two objects should be equal. Even if you don’t define x == y , the two objects should be behaviorally equivalent (see above for the meaning of that phrase) after an assignment.
  • If you define x == y and x != y , you should maintain the usual identities. For example, these expressions should return something convertible to bool , neither should change its operands, and x == y should have the same result as !(x != y) , and vice versa.
  • If you define inequality operators like x <= y and x < y , you should maintain the usual identities. For example, if x < y and y < z are both true, then x < z should also be true, etc. Similar comments for x >= y and x > y .
  • If you define inequality operators like x < y and x >= y , you should maintain the usual identities. For example, x < y should have the result as !(x >= y) . You can’t always do that, but you should get close and you should document any variances. Similar comments for x > y and !(x <= y) , etc.
  • Avoid overloading short-circuiting operators: x || y or x && y . The overloaded versions of these do not short-circuit — they evaluate both operands even if the left-hand operand “determines” the outcome, so that confuses users.
  • Avoid overloading the comma operator: x, y . The overloaded comma operator does not have the same ordering properties that it has when it is not overloaded, and that confuses users.
  • Don’t overload an operator that is non-intuitive to your users. This is called the Doctrine of Least Surprise. For example, although C++ uses std::cout << x for printing, and although printing is technically called inserting, and although inserting sort of sounds like what happens when you push an element onto a stack, don’t overload myStack << x to push an element onto a stack. It might make sense when you’re really tired or otherwise mentally impaired, and a few of your friends might think it’s “kewl,” but just say No.
  • Use common sense. If you don’t see “your” operator listed here, you can figure it out. Just remember the ultimate goals of operator overloading: to make life easier for your users, in particular to make their code cheaper to write and more obvious.

Caveat: the list is not exhaustive. That means there are other entries that you might consider “missing.” I know.

Caveat: the list contains guidelines, not hard and fast rules. That means almost all of the entries have exceptions, and most of those exceptions are not explicitly stated. I know.

Caveat: please don’t email me about the additions or exceptions. I’ve already spent way too much time on this particular answer.

How do I create a subscript operator for a Matrix class?

Use operator() rather than operator[] .

When you have multiple subscripts, the cleanest way to do it is with operator() rather than with operator[] . The reason is that operator[] always takes exactly one parameter, but operator() can take any number of parameters (in the case of a rectangular matrix, two parameters are needed).

For example:

Then you can access an element of Matrix m using m(i,j) rather than m[i][j] :

See the next FAQ for more detail on the reasons to use m(i,j) vs. m[i][j] .

Why shouldn’t my Matrix class’s interface look like an array-of-array?

Here’s what this FAQ is really all about: Some people build a Matrix class that has an operator[] that returns a reference to an Array object (or perhaps to a raw array , shudder), and that Array object has an operator[] that returns an element of the Matrix (e.g., a reference to a double ). Thus they access elements of the matrix using syntax like m[i][j] rather than syntax like m(i,j) .

The array-of-array solution obviously works, but it is less flexible than the operator() approach . Specifically, there are easy performance tuning tricks that can be done with the operator() approach that are more difficult in the [][] approach, and therefore the [][] approach is more likely to lead to bad performance, at least in some cases.

For example, the easiest way to implement the [][] approach is to use a physical layout of the matrix as a dense matrix that is stored in row-major form (or is it column-major; I can’t ever remember). In contrast, the operator() approach totally hides the physical layout of the matrix, and that can lead to better performance in some cases.

Put it this way: the operator() approach is never worse than, and sometimes better than, the [][] approach.

  • The operator() approach is never worse because it is easy to implement the dense, row-major physical layout using the operator() approach, so when that configuration happens to be the optimal layout from a performance standpoint, the operator() approach is just as easy as the [][] approach (perhaps the operator() approach is a tiny bit easier, but I won’t quibble over minor nits).
  • The operator() approach is sometimes better because whenever the optimal layout for a given application happens to be something other than dense, row-major, the implementation is often significantly easier using the operator() approach compared to the [][] approach.

As an example of when a physical layout makes a significant difference, a recent project happened to access the matrix elements in columns (that is, the algorithm accesses all the elements in one column, then the elements in another, etc.), and if the physical layout is row-major, the accesses can “stride the cache”. For example, if the rows happen to be almost as big as the processor’s cache size, the machine can end up with a “cache miss” for almost every element access. In this particular project, we got a 20% improvement in performance by changing the mapping from the logical layout (row,column) to the physical layout (column,row).

Of course there are many examples of this sort of thing from numerical methods, and sparse matrices are a whole other dimension on this issue. Since it is, in general, easier to implement a sparse matrix or swap row/column ordering using the operator() approach, the operator() approach loses nothing and may gain something — it has no down-side and a potential up-side.

Use the operator() approach .

I still don’t get it. Why shouldn’t my Matrix class’s interface look like an array-of-array?

The same reasons you encapsulate your data structures, and the same reason you check parameters to make sure they are valid.

A few people use [][] despite its limitations , arguing that [][] is better because it is faster or because it uses C-syntax. The problem with the “it’s faster” argument is that it’s not — at least not on the latest version of two of the world’s best known C++ compilers. The problem with the “uses C-syntax” argument is that C++ is not C. Plus, oh yea, the C-syntax makes it harder to change the data structure and harder to check parameter values.

The point of the previous two FAQs is that m(i,j) gives you a clean, simple way to check all the parameters and to hide (and therefore, if you want to, change) the internal data structure. The world already has way too many exposed data structures and way too many out-of-bounds parameters, and those cost way too much money and cause way too many delays and way too many defects.

Now everybody knows that you are different. You are clairvoyant with perfect knowledge of the future, and you know that no one will ever find any benefit from changing your matrix’s internal data structure. Plus you are a good programmer, unlike those slobs out there that occasionally pass wrong parameters, so you don’t need to worry about pesky little things like parameter checking. But even though you don’t need to worry about maintenance costs (no one ever needs to change your code), there might be one or two other programmers who aren’t quite perfect yet. For them, maintenance costs are high, defects are real, and requirements change. Believe it or not, every once in a while they need to (better sit down) change their code.

Admittedly my thongue wath in my theek. But there was a point. The point was that encapsulation and parameter-checking are not crutches for the weak. It’s smart to use techniques that make encapsulation and/or parameter checking easy. The m(i,j) syntax is one of those techniques.

Having said all that, if you find yourself maintaining a billion-line app where the original team used m[i][j] , or even if you are writing a brand new app and you just plain want to use m[i][j] , you can still encapsulate the data structure and/or check all your parameters. It’s not even that hard. However it does require a level of sophistication that, like it or not, average C++ programmers fear. Fortunately you are not average, so read on.

If you merely want to check parameters, just make sure the outer operator[] returns an object rather than a raw array , then that object’s operator[] can check its parameter in the usual way. Beware that this can slow down your program. In particular, if these inner array-like objects end up allocating their own block of memory for their row of the matrix, the performance overhead for creating / destroying your matrix objects can grow dramatically. The theoretical cost is still O( rows × cols ), but in practice, the overhead of the memory allocator ( new or malloc ) can be much larger than anything else, and that overhead can swamp the other costs. For instance, on two of the world’s best known C++ compilers, the separate-allocation-per-row technique was 10x slower than the one-allocation-for-the-entire-matrix technique . 10% is one thing, 10x is another.

If you want to check the parameters without the above overhead and/or if you want to encapsulate (and possibly change) the matrix’s internal data structure, follow these steps:

  • Add operator()(unsigned row, unsigned col) to the Matrix class.
  • Create nested class Matrix::Row . It should have a ctor with parameters (Matrix& matrix, unsigned row) , and it should store those two values in its this object.
  • Change Matrix::operator[](unsigned row) so it returns an object of class Matrix::Row , e.g., { return Row(*this,row); } .
  • Class Matrix::Row then defines its own operator[](unsigned col) which turns around and calls, you guessed it, Matrix::operator()(unsigned row, unsigned col) . If the Matrix::Row data members are called Matrix& matrix_ and unsigned row_ , the code for Matrix::Row::operator[](unsigned col) will be { return matrix_(row_, col); }

Next you will enable const overloading by repeating the above steps. You will create the const version of the various methods, and you will create a new nested class, probably called Matrix::ConstRow . Don’t forget to use const Matrix& instead of Matrix& .

Final step: find the joker who failed to read the previous FAQ and thonk him in the noggin.

If you have a decent compiler and if you judiciously use inlining , the compiler should optimize away the temporary objects. In other words, the operator[] -approach above will hopefully not be slower than what it would have been if you had directly called Matrix::operator()(unsigned row, unsigned col) in the first place. Of course you could have made your life simpler and avoided most of the above work by directly calling Matrix::operator()(unsigned row, unsigned col) in the first place. So you might as well directly call Matrix::operator()(unsigned row, unsigned col) in the first place.

Should I design my classes from the outside (interfaces first) or from the inside (data first)?

From the outside!

A good interface provides a simplified view that is expressed in the vocabulary of a user . In the case of OO software, the interface is normally the set of public methods of either a single class or a tight group of classes .

First think about what the object logically represents, not how you intend to physically build it. For example, suppose you have a Stack class that will be built by containing a LinkedList :

Should the Stack have a get() method that returns the LinkedList ? Or a set() method that takes a LinkedList ? Or a constructor that takes a LinkedList ? Obviously the answer is No, since you should design your interfaces from the outside-in. I.e., users of Stack objects don’t care about LinkedList s; they care about pushing and popping.

Now for another example that is a bit more subtle. Suppose class LinkedList is built using a linked list of Node objects, where each Node object has a pointer to the next Node :

Should the LinkedList class have a get() method that will let users access the first Node ? Should the Node object have a get() method that will let users follow that Node to the next Node in the chain? In other words, what should a LinkedList look like from the outside? Is a LinkedList really a chain of Node objects? Or is that just an implementation detail? And if it is just an implementation detail, how will the LinkedList let users access each of the elements in the LinkedList one at a time?

The key insight is the realization that a LinkedList is not a chain of Node s. 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 it might have a get() / set() pair to access its value stored in the Node (the value in the Node element is solely the responsibility of the LinkedList user, which is why there is a get() / set() pair that allows the user to freely manipulate that value).

Starting from the user’s perspective, we might want our LinkedList class to support operations that look similar to accessing an array using pointer arithmetic:

To implement this interface, LinkedList will need a begin() method and an end() method. These return a LinkedListIterator object. The LinkedListIterator will need a method to go forward, ++p ; a method to access the current element, *p ; and a comparison operator, p != a.end() .

The code follows. The important thing to notice is that LinkedList does not have any methods that let users access Node s. Node s are an implementation technique that is completely buried. This makes the LinkedList class safer (no chance a user will mess up the invariants and linkages between the various nodes), easier to use (users don’t need to expend extra effort keeping the node-count equal to the actual number of nodes, or any other infrastructure stuff), and more flexible (by changing a single typedef , users could change their code from using LinkedList to some other list-like class and the bulk of their code would compile cleanly and hopefully with improved performance characteristics).

Here are the methods that are obviously inlinable (probably in the same header file):

Conclusion: The linked list had two different kinds of data. The values of the elements stored in the linked list are the responsibility of the user of the linked list (and only the user; the linked list itself makes no attempt to prohibit users from changing the third element to 5), and the linked list’s infrastructure data ( next pointers, etc.), whose values are the responsibility of the linked list (and only the linked list; e.g., the linked list does not let users change (or even look at!) the various next pointers).

Thus the only get() / set() methods were to get and set the elements of the linked list, but not the infrastructure of the linked list. Since the linked list hides the infrastructure pointers/etc., it is able to make very strong promises regarding that infrastructure (e.g., if it were a doubly linked list, it might guarantee that every forward pointer was matched by a backwards pointer from the next Node ).

So, we see here an example of where the values of some of a class’s data is the responsibility of users (in which case the class needs to have get() / set() methods for that data) but the data that the class wants to control does not necessarily have get() / set() methods.

Note: the purpose of this example is not to show you how to write a linked-list class. In fact you should not “roll your own” linked-list class since you should use one of the “container classes” provided with your compiler. Ideally you’ll use one of the standard container classes such as the std::list<T> template.

How can I overload the prefix and postfix forms of operators ++ and -- ?

Via a dummy parameter.

Since the prefix and postfix ++ operators can have two definitions, the C++ language gives us two different signatures. Both are called operator++() , but the prefix version takes no parameters and the postfix version takes a dummy int . (Although this discussion revolves around the ++ operator, the -- operator is completely symmetric, and all the rules and guidelines that apply to one also apply to the other.)

Note the different return types: the prefix version returns by reference, the postfix version by value. If that’s not immediately obvious to you, it should be after you see the definitions (and after you remember that y = x++ and y = ++x set y to different things).

The other option for the postfix version is to return nothing:

However you must not make the postfix version return the this object by reference; you have been warned.

Here’s how you use these operators:

Assuming the return types are not ‘void’, you can use them in larger expressions:

Which is more efficient: i++ or ++i ?

++i is sometimes faster than, and is never slower than, i++ .

For intrinsic types like int , it doesn’t matter: ++i and i++ are the same speed. For class types like iterators or the previous FAQ’s Number class, ++i very well might be faster than i++ since the latter might make a copy of the this object.

The overhead of i++ , if it is there at all, won’t probably make any practical difference unless your app is CPU bound. For example, if your app spends most of its time waiting for someone to click a mouse, doing disk I/O, network I/O, or database queries, then it won’t hurt your performance to waste a few CPU cycles. However it’s just as easy to type ++i as i++ , so why not use the former unless you actually need the old value of i .

So if you’re writing i++ as a statement rather than as part of a larger expression, why not just write ++i instead? You never lose anything, and you sometimes gain something. Old line C programmers are used to writing i++ instead of ++i . E.g., they’ll say, for (i = 0; i < 10; i++) ... . Since this uses i++ as a statement, not as a part of a larger expression, then you might want to use ++i instead. For symmetry, I personally advocate that style even when it doesn’t improve speed, e.g., for intrinsic types and for class types with postfix operators that return void .

Obviously when i++ appears as a part of a larger expression, that’s different: it’s being used because it’s the only logically correct solution, not because it’s an old habit you picked up while programming in C.

Please Login to submit a recommendation.

If you don’t have an account, you can register for free.

Code With C

The Way to Programming

  • C Tutorials
  • Java Tutorials
  • Python Tutorials
  • PHP Tutorials
  • Java Projects

Mastering Operator Overloading: A Comprehensive Guide

CodeLikeAGirl

Mastering Operator Overloading: A Comprehensive Guide 🚀

Have you ever felt like you’re in a magical land where operators like +, -, or even == behave exactly the way you want them to? Well, my fellow tech enthusiasts, welcome to the whimsical world of operator overloading in C++! 🎩✨

Basics of Operator Overloading 🎯

What is operator overloading 🤔.

Let’s start from the very beginning – what on earth is this “operator overloading” that we keep hearing about? 🤷‍♀️ It’s like giving these operators a new superpower! 🦸‍♀️ Operator overloading allows you to redefine the way operators work with user-defined data types. In simple terms, you get to teach C++ some new tricks! 🎩🐇

Why Use Operator Overloading? 🤓

Now, why bother with all this operator overloading business, you ask? 💭 Well, imagine making your code more elegant and readable by using + to concatenate strings or comparing objects with ==. It’s like adding a sprinkle of magic to your code, making it more intuitive and user-friendly! ✨🪄

Implementing Operator Overloading in C++ 🛠️

Syntax for operator overloading 📝.

To dip your toes into the enchanting waters of operator overloading, you need to know the syntax! It involves creating a function with a special name, ensuring that the compiler knows how to handle those magical new tricks you’re teaching it. Ah, it’s like writing a secret incantation that only your program can understand ! 🔮✍️

Overloading Unary and Binary Operators 🔢

Unary, binary – wait, what now? Don’t worry, it’s just a fancy way of saying you can overload operators like + or – for different uses! Whether you’re working with one operand or two, operator overloading lets you redefine their behavior based on your needs. It’s like juggling different tasks with the same tool! 🤹‍♂️🔧

Best Practices for Operator Overloading 🌟

Avoiding ambiguity in operator overloading ❌.

Ah, the dreaded ambiguity – the dark side of operator overloading! To steer clear of confusion, make sure your overloaded operators are crystal clear in their intentions. You wouldn’t want your program scratching its virtual head trying to decipher your mystical code, would you? 🤯🧙‍♂️

Overloading Commonly Used Operators 💡

When in doubt, remember – stick to the classics! Overloading familiar operators like +, -, or == can make your code more intuitive and user-friendly. It’s like speaking the language of C++ fluently, with a hint of your own unique dialect! 🗣️🌐

Advanced Techniques in Operator Overloading 💡

Overloading assignment operator (=) 📚.

Ah, the humble assignment operator – the unsung hero of C++ . By overloading this operator, you can customize how your objects are assigned values. It’s like giving your programs a personalized touch, ensuring they get all dressed up in the perfect outfit! 👗👔

Overloading Increment (++) and Decrement (–) Operators 🔝

Feeling adventurous? How about tinkering with the ++ and — operators? By overloading these bad boys, you can define how your objects increment or decrement. It’s like a virtual dance, where your objects move to the beat of your custom-made drum! 🥁🎶

Common Pitfalls to Avoid in Operator Overloading 🕳️

Handling memory management in operator overloading 🧠.

Ah, memory management – the bane of many programmers! When overloading operators, be extra cautious with memory allocation and deallocation. One wrong move, and your program could be lost in a memory maze, desperately searching for a way out! 🧟‍♂️🤖

Ensuring Consistency in Overloaded Operators 🤝

Consistency is key in the magical realm of operator overloading! Make sure that similar operations behave uniformly across your code. It’s like maintaining harmony in a chaotic symphony, ensuring that every note plays in perfect unison! 🎻🎶

In Closing 🌈

Overall, mastering the art of operator overloading in C++ is like wielding a powerful magic wand in the world of programming. By understanding the basics, embracing best practices, exploring advanced techniques, and steering clear of common pitfalls, you can elevate your code to new heights of elegance and efficiency! 🚀🌟

Thank you for joining me on this enchanting journey through the realms of operator overloading. Remember, in the magical land of C++, the possibilities are as endless as the stars in the night sky! 🌌✨

Now go forth, brave coders, and may your operator overloading adventures be filled with joy, laughter, and of course, lots of magical moments! 🎉🔮

P.S. Keep coding, keep creating, and always remember – the code is strong with this one! 💪👩‍💻

Program Code – Mastering Operator Overloading: A Comprehensive Guide

### code output:, ### code explanation:.

The provided code example illustrates the essence of operator overloading in C++ .

Architecture:

At its heart, it comprises a class named ComplexNumber . This class encapsulates two private attributes: real and imaginary , representing the real and imaginary parts of a complex number, respectively.

Logic and Implementation Details:

  • Constructor Initialization: The constructor ComplexNumber initializes these two attributes. If values are not provided during object creation, it defaults to 0.0.
  • Display Method: There’s a handy display method to output the complex number in a human-readable format, i.e., ‘Complex Number: X + Yi.
  • Addition (‘+’ operator): It overloads the ‘+’ operator using the member function operator + to add two complex numbers. It takes an object of ComplexNumber as a parameter ( const ComplexNumber& obj ) representing the second operand. Inside, it creates a temporary object temp , calculates the summation of real and imaginary parts separately, and returns temp .
  • Subtraction (‘-’ operator): Very similar to addition, it also overloads the ‘-‘ operator using the member function operator - for subtracting two complex numbers. It follows a procedure analogous to addition, calculating the difference of both real and imaginary parts separately.
  • Main Function: In main() , two ComplexNumber objects c1 and c2 are instantiated with specific values. Then, leveraging our overloaded operators, we add ( c1 + c2 ) and subtract ( c1 - c2 ) these complex numbers and display the results using the display() method.

How it Achieves its Objectives:

The demonstration efficiently achieves its educational aim by intricately showing how operators can be overloaded to perform operations according to the nature of user-defined data types , in this case, complex numbers. Rather than just being confined to the built-in data types, operator overloading extends the expressiveness of C++ to accommodate complex operations in a manner that’s both intuitive and elegant for the programmer.

Frequently Asked Questions

What is operator overloading in c++.

Operator overloading in C++ allows us to redefine the way operators work for user-defined data types . This means we can use operators like +, -, *, /, etc., with custom objects just like built-in data types.

How does operator overloading work in C++?

In C++, operator overloading is achieved by defining a function to overload an operator. When an operator is used with objects of a class, the corresponding function is called to perform the operation.

Can we overload all operators in C++?

No, not all operators can be overloaded in C++. Some operators, like sizeof , :: , .* , etc., cannot be overloaded. It’s essential to understand which operators can and cannot be overloaded in C++.

What are the benefits of operator overloading?

Operator overloading can make our code more readable and intuitive by allowing us to use familiar operators with custom types. It can also lead to code that closely resembles mathematical expressions, making the code easier to understand .

What are some common mistakes to avoid when overloading operators in C++?

One common mistake when overloading operators in C++ is not handling edge cases or boundary conditions properly. It’s crucial to test the overloaded operators thoroughly to ensure they work as expected in all scenarios.

Are there any performance implications of operator overloading in C++?

Yes, there can be performance implications when using operator overloading in C++. Overloading operators can introduce overhead compared to regular function calls. It’s essential to consider the performance impact when overloading operators in performance-critical code.

How can I decide when to use operator overloading in my C++ code?

The decision to use operator overloading in C++ should be based on whether it enhances the readability and maintainability of the code. If overloading an operator makes the code more natural to read and less error-prone, it can be a good choice.

Where can I find more resources to learn about mastering operator overloading in C++?

There are plenty of online resources, tutorials, and books available to learn more about mastering operator overloading in C++. Websites like GeeksforGeeks, tutorials from cppreference.com, and books like “Effective C++” by Scott Meyers can be valuable sources of information.

You Might Also Like

The significance of ‘c’ in c programming language, c programming languages: understanding the basics and beyond, exploring the c programming language: from basics to advanced concepts, object-oriented programming: the pillar of modern software development, object-oriented coding: best practices and techniques.

Avatar photo

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Latest Posts

62 Creating a Google Sheet to Track Google Drive Files: Step-by-Step Guide

Creating a Google Sheet to Track Google Drive Files: Step-by-Step Guide

codewithc 61 Cutting-Edge Artificial Intelligence Project Unveiled in Machine Learning World

Cutting-Edge Artificial Intelligence Project Unveiled in Machine Learning World

75 Enhancing Exams with Image Processing: E-Assessment Project

Enhancing Exams with Image Processing: E-Assessment Project

73 Cutting-Edge Blockchain Projects for Cryptocurrency Enthusiasts - Project

Cutting-Edge Blockchain Projects for Cryptocurrency Enthusiasts – Project

67 Artificial Intelligence Marvel: Cutting-Edge Machine Learning Project

Artificial Intelligence Marvel: Cutting-Edge Machine Learning Project

Privacy overview.

en_US

Sign in to your account

Username or Email Address

Remember Me

A centralized delay-sensitive hierarchical computation offloading in fog radio access networks

  • Published: 05 September 2024

Cite this article

c overload assignment operator array

  • Samira Taheri 1 ,
  • Neda Moghim 1 ,
  • Naser Movahhedinia 1 &
  • Sachin Shetty 2  

MEC (Multi-access Edge Computing) is vital in 5G and beyond (B5G) for reducing latency and enhancing network efficiency through local processing, crucial for real-time applications and improved security. This drives the adoption of advanced architectures like Fog Radio Access Network (F-RAN), which uses distributed resources from Radio Resource Heads (RRHs) or fog nodes to enable parallel computation. Each user equipment (UE) task can be processed by RRHs, fog access points, cloud servers, or the UE itself, depending on resource capacities. We propose MoNoR, a centralized approach for optimal task processing in F-RAN. MoNoR optimizes the selection of offloading modes, assignment of tasks to computation nodes, and allocation of radio resources using global network information. Given the computational complexity of this endeavor, we employ an evolutionary optimization technique rooted in Genetic Algorithms to address the problem efficiently. Simulations show MoNoR's superiority in minimizing latency over previous F-RAN offloading strategies.

This is a preview of subscription content, log in via an institution to check access.

Access this article

Subscribe and save.

  • Get 10 units per month
  • Download Article/Chapter or eBook
  • 1 Unit = 1 Article or 1 Chapter
  • Cancel anytime

Price includes VAT (Russian Federation)

Instant access to the full article PDF.

Rent this article via DeepDyve

Institutional subscriptions

c overload assignment operator array

Explore related subjects

  • Artificial Intelligence

Data availability

No datasets were generated or analyzed during the current study.

X. Shen, X. Song, X. Meng, and C. Jia, "Edge Computing Sever Selection in Fog Radio Access Networks," in 2018 IEEE/CIC International Conference on Communications in China (ICCC Workshops), 2018: IEEE, pp. 287–291.

M. Xu, Z. Zhao, M. Peng, Z. Ding, T. Q. Quek, and W. Bai, "Performance analysis of computation offloading in fog-radio access networks," in ICC 2019–2019 IEEE International Conference on Communications (ICC), 2019: IEEE, pp. 1–6.

Barbarossa S, Sardellitti S, Di Lorenzo P (2014) Communicating while computing: Distributed mobile cloud computing over 5G heterogeneous networks. IEEE Signal Process Mag 31(6):45–55

Article   Google Scholar  

Sun X, Ansari N (2016) EdgeIoT: mobile edge computing for the Internet of Things. IEEE Commun Mag 54(12):22–29

Jiang C, Cheng X, Gao H, Zhou X, Wan J (2019) Toward computation offloading in edge computing: a survey. IEEE Access 7:131543–131558

Deng S, Huang L, Taheri J, Zomaya AY (2014) Computation offloading for service workflow in mobile cloud computing. IEEE Trans Parallel Distrib Syst 26(12):3317–3329

Chiang M, Zhang T (2016) Fog and IoT: an overview of research opportunities. IEEE Internet Things J 3(6):854–864

Mach P, Becvar Z (2017) Mobile edge computing: a survey on architecture and computation offloading. IEEE Commun Surv Tutor 19(3):1628–1656

Peng M, Yan S, Zhang K, Wang C (2016) Fog-computing-based radio access networks: issues and challenges. IEEE Network 30(4):46–53

Kiran N, Pan C, Wang S, Yin C (2019) Joint resource allocation and computation offloading in mobile edge computing for SDN based wireless networks. J Commun Netw 22(1):1–11

Hossain MF, Mahin AU, Debnath T, Mosharrof FB, Islam KZ (2019) Recent research in cloud radio access network (C-RAN) for 5G cellular systems-A survey. J Netw Comput Appl 139:31–48

Checko A et al (2014) Cloud RAN for mobile networks—A technology overview. IEEE Commun Surv Tutor 17(1):405–426

Peng M, Wang C, Lau V, Poor HV (2015) Fronthaul-constrained cloud radio access networks: Insights and challenges. IEEE Wirel Commun 22(2):152–160

Guizani Z, Hamdi N (2017) CRAN, H-CRAN, and F-RAN for 5G systems: key capabilities and recent advances. Int J Network Manage 27(5):e1973

Hu H et al (2021) Computation offloading analysis in clustered fog radio access networks with repulsion. IEEE Trans Veh Technol 70(10):10804–10819

Q. Li, J. Lei, and J. Lin. 2018. Min-max latency optimization for multiuser computation offloading in fog-radio access networks," in 2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP), 2018: IEEE, pp. 3754-3758.

Rahman GS, Dang T, Ahmed M (2020) Deep reinforcement learning based computation offloading and resource allocation for low-latency fog radio access networks. Intell Converg Netw 1(3):243–257

Hussein MK, Mousa MH (2020) Efficient task offloading for IoT-based applications in fog computing using ant colony optimization. IEEE Access 8:37191–37201

T.C. Chiu, W.H. Chung, A.C. Pang, Y.J. Yu, P.H. Yen. 2016. Ultra-low latency service provision in 5G fog-radio access networks, in 2016 IEEE 27th Annual International Symposium on Personal, Indoor, and Mobile Radio Communications (PIMRC), 2016: IEEE, pp. 1-6.

Hu X, Wang L, Wong K-K, Tao M, Zhang Y, Zheng Z (2019) Edge and central cloud computing: a perfect pairing for high energy efficiency and low-latency. IEEE Trans Wireless Commun 19(2):1070–1083

Dang T, Peng M (2019) Joint radio communication, caching, and computing design for mobile virtual reality delivery in fog radio access networks. IEEE J Sel Areas Commun 37(7):1594–1607

Zhang W et al (2023) Multiuser computation offloading in fog-radio access networks. Digital Commun Netw. https://doi.org/10.1016/j.dcan.2023.05.011

Liang K, Zhao L, Zhao X, Wang Y, Ou S (2016) Joint resource allocation and coordinated computation offloading for fog radio access networks. China Commun 13(Supplement 2):131–139

Sun Y, Peng M, Mao S (2018) Deep reinforcement learning-based mode selection and resource management for green fog radio access networks. IEEE Internet Things J 6(2):1960–1971

C. Wang, Y. Sun, and Y. Ren. Distributed User Association for Computation Offloading in Green Fog Radio Access Networks, In: 2020 Information Communication Technologies Conference (ICTC), 2020: IEEE, pp. 75-80.

Bai W, Wang Z (2023) Joint optimization of resources in fog-radio access network with binary computation offloading,". Mob Inf Syst. https://doi.org/10.1155/2023/1687672

Vu DN et al (2019) Joint energy and latency optimization for upstream IoT offloading services in fog radio access networks. Transact Emerging Telecommun Technol 30(4):e3497

S. Bu, T. Zhao, and Z. Yin. 2018. Resource allocation for computation offloading in fog radio access networks. In: 2018 IEEE/CIC International Conference on Communications in China (ICCC Workshops): IEEE, pp. 267-271.

Jijin J, Seet B-C, Chong PHJ (2020) Multi-objective optimization of task-to-node assignment in opportunistic fog RAN. Electronics 9(3):474

J. Jijin, B.-C. Seet, P. H. J. Chong, H. Jarrah. 2017. Service load balancing in fog-based 5G radio access networks, In: 2017 IEEE 28th Annual International Symposium on Personal, Indoor, and Mobile Radio Communications (PIMRC). pp. 1–5.

Z. Wu, K. Wang, H. Ji, and V. C. Leung. 2016. A computing offloading algorithm for F-RAN with limited capacity fronthaul. In: 2016 IEEE International Conference on Network Infrastructure and Digital Content (IC-NIDC), 2016: IEEE, pp. 78-83.

Lema MA, Laya A, Mahmoodi T, Cuevas M, Sachs J, Markendahl J, Dohler M (2017) Business case and technology analysis for 5G low latency applications. IEEE Access 5:5917–5935

Google Scholar  

Download references

No funding was received for conducting this study.

Author information

Authors and affiliations.

Department of Computer Engineering, University of Isfahan, Isfahan, Iran

Samira Taheri, Neda Moghim & Naser Movahhedinia

Department of Computational Modeling and Simulation Engineering, Virginia Modeling, Analysis, and Simulation Center, Old Dominion University, Suffolk, VA, 23435, USA

Sachin Shetty

You can also search for this author in PubMed   Google Scholar

Contributions

Samira Taheri worked in investigation, conceptualization, methodology, simulation, validation, writing—original draft, visualization, and writing—review & editing. Neda Moghim helped in conceptualization, methodology, validation, writing—original draft, writing—review & editing, supervision, and project administration. Naser Movahedinia helped in methodology, validation, writing—review & editing, and supervision. Sachin Shetty helped in methodology, validation, and writing—review & editing.

Corresponding author

Correspondence to Neda Moghim .

Ethics declarations

Conflict of interest.

The authors declare no competing interests.

Additional information

Publisher's note.

Springer Nature remains neutral with regard to jurisdictional claims in published maps and institutional affiliations.

Rights and permissions

Springer Nature or its licensor (e.g. a society or other partner) holds exclusive rights to this article under a publishing agreement with the author(s) or other rightsholder(s); author self-archiving of the accepted manuscript version of this article is solely governed by the terms of such publishing agreement and applicable law.

Reprints and permissions

About this article

Taheri, S., Moghim, N., Movahhedinia, N. et al. A centralized delay-sensitive hierarchical computation offloading in fog radio access networks. J Supercomput (2024). https://doi.org/10.1007/s11227-024-06454-6

Download citation

Accepted : 12 August 2024

Published : 05 September 2024

DOI : https://doi.org/10.1007/s11227-024-06454-6

Share this article

Anyone you share the following link with will be able to read this content:

Sorry, a shareable link is not currently available for this article.

Provided by the Springer Nature SharedIt content-sharing initiative

  • Computation offloading
  • Cloud computing
  • Fog computing
  • Computation-intensive applications
  • Fog radio access networks
  • Find a journal
  • Publish with us
  • Track your research
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Correctly overload assignment operator for classes with pointer members

Correct me if I'm wrong:

I understand that when having a class with members that are pointers, a copy of a class object will result in that the pointers representing the same memory address. This can result in changes done to one class object to affect all copies of this object.

A solution to this can be to overload the = operator. Given the example below, with an attempt to create a dynamic array class, why does making changes to MyArray1 change MyArray2 :

Array Class:

Example output:

As seen above, changes made to MyArray1, changes MyArray2. I assume the overloading of = is wrong, but how would I write it correctly?

Thanks to Chris Dodd in the comments, I realized it's just to implement a copy constructor like this in my class:

  • overloading

juanchopanza's user avatar

  • You've violated the rule of three –  Chris Dodd Commented Sep 8, 2016 at 6:33
  • Yes, I was realising that, that's why I deleted my comment same time as you anwered! Thank you, I will give it a shot:) –  remi Commented Sep 8, 2016 at 6:43

3 Answers 3

There is more than one issue with your code. Most importantly, as pointed out in the comment to to the question, except for writing your own assignment operator, you need to write your copy constructor as well (and implement a destructor).

Second thing is, that your assignment operator takes argument by value instead of by reference, which causes default copy constructor to create a copy of your MyArray1 before it's passed to assignment operator. This is where the direct source of your problem lays.

Another thing is that your assignment operator behaves like a move assignment instead of copy assignment, meaning it replaces the original item's values with its current (default) value.

Lastly, you really want to implement the destructor, so that it deletes your array instead of just leaking it.

Summing up, you want something like this (edit: copy assignment checks inspired by Timothy's answer):

slawekwin's user avatar

  • I noticed by changing my assignement operator to take a reference, and reruning the code, MyArray1 "loses" all it's information after doing: MyArray2 = MyArray1 –  remi Commented Sep 8, 2016 at 6:55
  • 1 "Second thing is, that your assignment operator takes argument by value instead of by reference" It is the copy any swap idiom. –  juanchopanza Commented Sep 8, 2016 at 7:20
  • @juanchopanza yes, you are obviously right, I doubt OP understood how it worked, though (because of not implementing copy constructor) –  slawekwin Commented Sep 8, 2016 at 7:51
  • can u please explain why compiler says error: this ‘if’ clause does not guard... [-Werror=misleading-indentation] 31 | if (this == &arr2) –  user786 Commented Aug 17, 2021 at 10:05

So, I see three issues.

You should really have a copy constructor. You never know what optimizations your compiler might make (changing assignment to copy-constructor, etc...).

you should check for self-assignment when assigning. When doing the assignment you want to get rid of your old data and replace it with the new. If you do self assignment, you'll run into errors (aka delete your data before you reassign to yourself) plus it's extra work you don't need to do.

you don't handle your dynamically allocated data when you call the destructor. This will cause a memory-leak and for long running programs becomes a large problem.

Code Updates:

Timothy Murphy's user avatar

  • Re. point 2, OP is using the copy and swap idiom. That would be robust against self-assignment. But it is broken because of the copy constructor. –  juanchopanza Commented Sep 8, 2016 at 7:19
  • Fair enough. Although for large arrays that causes a lot of extra work for self assignment. –  Timothy Murphy Commented Sep 8, 2016 at 8:01
  • 2 You should use delete [] for array deletion. –  DigviJay Patil Commented Sep 23, 2019 at 10:01

you can avoid all of these if you want to make = only but not Array MyArray1=MyArray2 because it also needs a copy constructor you can do this

passing by reference solve the problem but if you want to do

you need a copy constructor

and if you want selfassignment you must check

Saman Salehi's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ pointers overloading or ask your own question .

  • The Overflow Blog
  • The hidden cost of speed
  • The creator of Jenkins discusses CI/CD and balancing business with open source
  • Featured on Meta
  • Announcing a change to the data-dump process
  • Bringing clarity to status tag usage on meta sites
  • What does a new user need in a homepage experience on Stack Overflow?
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • Using rule-based symbology for overlapping layers in QGIS
  • Creating Layout of 2D Board game
  • Short story about humanoid creatures living on ice, which can swim under the ice and eat the moss/plants that grow on the underside of the ice
  • How Does This Antique Television Circuit Work?
  • Referencing an other tikzpicture without overlay
  • Microsoft SQL In-Memory OLTP in SQL Express 2019/2022
  • Confusion about time dilation
  • 99 camaro overheating
  • How should I tell my manager that he could delay my retirement with a raise?
  • Current in a circuit is 50% lower than predicted by Kirchhoff's law
  • Dirichlet Series that fail to be L-functions
  • Problem about ratio between circumradius and inradius
  • Does the average income in the US drop by $9,500 if you exclude the ten richest Americans?
  • I'm a little embarrassed by the research of one of my recommenders
  • What are the most commonly used markdown tags when doing online role playing chats?
  • Does a party have to wait 1d4 hours to start a Short Rest if no healing is available and an ally is only stabilized?
  • What's the difference? lie down vs lie
  • How to run only selected lines of a shell script?
  • Long and protected macros in LaTeX3
  • How can I close all other windows on the same side of a vertical split where the current window is?
  • Matrix Multiplication & Addition
  • Clarification Regarding a Possible Typo in David J. Griffiths' Introduction to Electrodynamics
  • What's "the archetypal book" called?
  • How do I learn more about rocketry?

c overload assignment operator array

  • C++ Classes and Objects
  • C++ Polymorphism
  • C++ Inheritance
  • C++ Abstraction
  • C++ Encapsulation
  • C++ OOPs Interview Questions
  • C++ OOPs MCQ
  • C++ Interview Questions
  • C++ Function Overloading
  • C++ Programs
  • C++ Preprocessor
  • C++ Templates

Operator Overloading in C++

in C++, Operator overloading is a compile-time polymorphism. It is an idea of giving special meaning to an existing operator in C++ without changing its original meaning.

In this article, we will further discuss about operator overloading in C++ with examples and see which operators we can or cannot overload in C++.

C++ Operator Overloading

C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading. Operator overloading is a compile-time polymorphism. For example, we can overload an operator ‘+’ in a class like String so that we can concatenate two strings by just using +. Other example classes where arithmetic operators may be overloaded are Complex Numbers, Fractional Numbers, Big integers, etc.

int a; float b,sum; sum = a + b;

Here, variables “a” and “b” are of types “int” and “float”, which are built-in data types. Hence the addition operator ‘+’ can easily add the contents of “a” and “b”. This is because the addition operator “+” is predefined to add variables of built-in data type only. 

Implementation:

// C++ Program to Demonstrate the // working/Logic behind Operator // Overloading class A { statements ; }; int main () { A a1 , a2 , a3 ; a3 = a1 + a2 ; return 0 ; }

In this example, we have 3 variables “a1”, “a2” and “a3” of type “class A”. Here we are trying to add two objects “a1” and “a2”, which are of user-defined type i.e. of type “class A” using the “+” operator. This is not allowed, because the addition operator “+” is predefined to operate only on built-in data types. But here, “class A” is a user-defined type, so the compiler generates an error. This is where the concept of “Operator overloading” comes in.

Now, if the user wants to make the operator “+” add two class objects, the user has to redefine the meaning of the “+” operator such that it adds two class objects. This is done by using the concept of “Operator overloading”. So the main idea behind “Operator overloading” is to use C++ operators with class variables or class objects. Redefining the meaning of operators really does not change their original meaning; instead, they have been given additional meaning along with their existing ones.

Example of Operator Overloading in C++

// C++ Program to Demonstrate // Operator Overloading #include <iostream> using namespace std ; class Complex { private : int real , imag ; public : Complex ( int r = 0 , int i = 0 ) { real = r ; imag = i ; } // This is automatically called when '+' is used with // between two Complex objects Complex operator + ( Complex const & obj ) { Complex res ; res . real = real + obj . real ; res . imag = imag + obj . imag ; return res ; } void print () { cout << real << " + i" << imag << '\n' ; } }; int main () { Complex c1 ( 10 , 5 ), c2 ( 2 , 4 ); Complex c3 = c1 + c2 ; c3 . print (); }

Difference between Operator Functions and Normal Functions

Operator functions are the same as normal functions. The only differences are, that the name of an operator function is always the operator keyword followed by the symbol of the operator, and operator functions are called when the corresponding operator is used. 

#include <iostream> using namespace std ; class Complex { private : int real , imag ; public : Complex ( int r = 0 , int i = 0 ) { real = r ; imag = i ; } void print () { cout << real << " + i" << imag << endl ; } // The global operator function is made friend of this // class so that it can access private members friend Complex operator + ( Complex const & c1 , Complex const & c2 ); }; Complex operator + ( Complex const & c1 , Complex const & c2 ) { return Complex ( c1 . real + c2 . real , c1 . imag + c2 . imag ); } int main () { Complex c1 ( 10 , 5 ), c2 ( 2 , 4 ); Complex c3 = c1 + c2 ; // An example call to &quot;operator+&quot; c3 . print (); return 0 ; }

Can We Overload All Operators?  

Almost all operators can be overloaded except a few. Following is the list of operators that cannot be overloaded. 

sizeof typeid Scope resolution (::) Class member access operators (.(dot), .* (pointer to member operator)) Ternary or conditional (?:)

Operators that can be Overloaded in C++

We can overload

Unary operators Binary operators Special operators ( [ ], (), etc)

But, among them, there are some operators that cannot be overloaded. They are

Scope resolution operator [Tex](::)[/Tex] Member selection operator                              Member selection through  *

Pointer to a member variable

  • Conditional operator [Tex](?:)[/Tex]
  • Sizeof operator  sizeof()
Operators that can be overloadedExamples
Binary Arithmetic+, -, *, /, %
Unary Arithmetic +, -, ++, —
Assignment=, +=,*=, /=,-=, %=
Bitwise& , | , << , >> , ~ , ^
De-referencing(->)
Dynamic memory allocation,
De-allocation
New, delete 
Subscript[ ]
Function call ()
Logical &,  | |, !
Relational>, < , = =, <=, >=

Why can’t the above-stated operators be overloaded?

1. sizeof operator.

This returns the size of the object or datatype entered as the operand. This is evaluated by the compiler and cannot be evaluated during runtime. The proper incrementing of a pointer in an array of objects relies on the sizeof operator implicitly. Altering its meaning using overloading would cause a fundamental part of the language to collapse.

2. typeid Operator

This provides a CPP program with the ability to recover the actually derived type of the object referred to by a pointer or reference. For this operator, the whole point is to uniquely identify a type. If we want to make a user-defined type ‘look’ like another type, polymorphism can be used but the meaning of the typeid operator must remain unaltered, or else serious issues could arise.

3. Scope resolution (::) Operator

This helps identify and specify the context to which an identifier refers by specifying a namespace. It is completely evaluated at runtime and works on names rather than values. The operands of scope resolution are note expressions with data types and CPP has no syntax for capturing them if it were overloaded. So it is syntactically impossible to overload this operator.

4. Class member access operators (.(dot ), .* (pointer to member operator))

The importance and implicit use of class member access operators can be understood through the following example:

// C++ program to demonstrate operator overloading // using dot operator #include <iostream> using namespace std ; class ComplexNumber { private : int real ; int imaginary ; public : ComplexNumber ( int real , int imaginary ) { this -> real = real ; this -> imaginary = imaginary ; } void print () { cout << real << " + i" << imaginary ; } ComplexNumber operator + ( ComplexNumber c2 ) { ComplexNumber c3 ( 0 , 0 ); c3 . real = this -> real + c2 . real ; c3 . imaginary = this -> imaginary + c2 . imaginary ; return c3 ; } }; int main () { ComplexNumber c1 ( 3 , 5 ); ComplexNumber c2 ( 2 , 4 ); ComplexNumber c3 = c1 + c2 ; c3 . print (); return 0 ; }

Explanation:

The statement ComplexNumber c3 = c1 + c2; is internally translated as ComplexNumber c3 = c1.operator+ (c2); in order to invoke the operator function. The argument c1 is implicitly passed using the ‘.’ operator. The next statement also makes use of the dot operator to access the member function print and pass c3 as an argument. 

Besides, these operators also work on names and not values and there is no provision (syntactically) to overload them.

5. Ternary or conditional (?:) Operator

The ternary or conditional operator is a shorthand representation of an if-else statement. In the operator, the true/false expressions are only evaluated on the basis of the truth value of the conditional expression. 

conditional statement ? expression1 (if statement is TRUE) : expression2 (else)

A function overloading the ternary operator for a class say ABC using the definition

ABC operator ?: (bool condition, ABC trueExpr, ABC falseExpr);

would not be able to guarantee that only one of the expressions was evaluated. Thus, the ternary operator cannot be overloaded.

Important Points about Operator Overloading  

1) For operator overloading to work, at least one of the operands must be a user-defined class object.

2) Assignment Operator: Compiler automatically creates a default assignment operator with every class. The default assignment operator does assign all members of the right side to the left side and works fine in most cases (this behavior is the same as the copy constructor). See this for more details.

3) Conversion Operator: We can also write conversion operators that can be used to convert one type to another type. 

Example:  

// C++ Program to Demonstrate the working // of conversion operator #include <iostream> using namespace std ; class Fraction { private : int num , den ; public : Fraction ( int n , int d ) { num = n ; den = d ; } // Conversion operator: return float value of fraction operator float () const { return float ( num ) / float ( den ); } }; int main () { Fraction f ( 2 , 5 ); float val = f ; cout << val << '\n' ; return 0 ; }

Overloaded conversion operators must be a member method. Other operators can either be the member method or the global method.

4) Any constructor that can be called with a single argument works as a conversion constructor, which means it can also be used for implicit conversion to the class being constructed. 

// C++ program to demonstrate can also be used for implicit // conversion to the class being constructed #include <iostream> using namespace std ; class Point { private : int x , y ; public : Point ( int i = 0 , int j = 0 ) { x = i ; y = j ; } void print () { cout << "x = " << x << ", y = " << y << '\n' ; } }; int main () { Point t ( 20 , 20 ); t . print (); t = 30 ; // Member x of t becomes 30 t . print (); return 0 ; }

x = 20, y = 20 x = 30, y = 0

Quiz on Operator Overloading

Please Login to comment...

Similar reads.

  • cpp-operator-overloading
  • cpp-overloading
  • Top Android Apps for 2024
  • Top Cell Phone Signal Boosters in 2024
  • Best Travel Apps (Paid & Free) in 2024
  • The Best Smart Home Devices for 2024
  • 15 Most Important Aptitude Topics For Placements [2024]

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

IMAGES

  1. Overloading assignment operator in C++

    c overload assignment operator array

  2. Assignment Operator Overloading In C++

    c overload assignment operator array

  3. Assignment Operators in C

    c overload assignment operator array

  4. Assignment Operator Overloading in C++

    c overload assignment operator array

  5. C++ Overload Cast Operator: Mastering Type Conversions

    c overload assignment operator array

  6. Operator Overloading in c++

    c overload assignment operator array

VIDEO

  1. Inquirer Error

  2. Assignment Operator Overloading In C++

  3. Operators in C++

  4. Operator Overloading in C++

  5. C++ Tutorial 12 : Operator Overloading & File I/O

  6. Overloading operators

COMMENTS

  1. c++

    @K-ballo: His implementation, perhaps by accident, actually covers the problem of self assignment. It checks if the arrays are the same size. If they're not the same size, they can't be the same object.

  2. 21.12

    21.12 — Overloading the assignment operator. Alex July 22, 2024. The copy assignment operator (operator=) is used to copy values from one object to another already existing object. As of C++11, C++ also supports "Move assignment". We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .

  3. C++ Assignment Operator Overloading

    The assignment operator,"=", is the operator used for Assignment. It copies the right value into the left value. Assignment Operators are predefined to operate only on built-in Data types. Assignment operator overloading is binary operator overloading. Overloading assignment operator in C++ copies all values of one object to another object.

  4. operator overloading

    In those situations where copy assignment cannot benefit from resource reuse (it does not manage a heap-allocated array and does not have a (possibly transitive) member that does, such as a member std::vector or std::string), there is a popular convenient shorthand: the copy-and-swap assignment operator, which takes its parameter by value (thus working as both copy- and move-assignment ...

  5. operator overloading

    When a user-defined class overloads the function call operator, operator(), it becomes a FunctionObject type. Many standard algorithms, from std::sort to std::accumulate accept objects of such types to customize behavior. There are no particularly notable canonical forms of operator(), but to illustrate the usage.

  6. Overload resolution

    3) built-in candidates: For operator,, the unary operator &, and operator->, the set of built-in candidates is empty.For other operators built-in candidates are the ones listed in built-in operator pages as long as all operands can be implicitly converted to their parameters. If any built-in candidate has the same parameter list as a non-member candidate or rewritten non-member candidate ...

  7. operator overloading

    Overloaded operators. When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following: Expression. As member function.

  8. Copy Constructor vs Assignment Operator in C++

    C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. Consider the following C++ program. Explanation: Here, t2 = t1; calls the assignment operator, same as t2.operator= (t1); and Test t3 = t1; calls the copy constructor ...

  9. Overloading Subscript or array index operator [] in C++

    The range of a C++ array is from array[0] to array[size - 1]. However, C++ supports positive and negative subscripts. Negative subscripts must fall within array boundaries; if they do not, the results are unpredictable. ... Prerequisite: Operator Overloading The assignment operator,"=", is the operator used for Assignment. It copies the right ...

  10. c++

    would use your assignment operator. From the looks of it you want to have an overloaed assignment operator applied when using the subscript operator. The only way to get something like this to work is using a proxy class: Proxy(Array* array, int* element); void operator= (int rhs) {. array->two = rhs; *element = rhs;

  11. Copy assignment operator

    the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial. A trivial copy assignment operator makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD types) are trivially copy-assignable.

  12. 21.9

    Why operator[] returns a reference. Let's take a closer look at how list[2] = 3 evaluates. Because the subscript operator has a higher precedence than the assignment operator, list[2] evaluates first.list[2] calls operator[], which we've defined to return a reference to list.m_list[2].Because operator[] is returning a reference, it returns the actual list.m_list[2] array element.

  13. Operator Overloading, C++ FAQ

    It allows you to provide an intuitive interface to users of your class, plus makes it possible for templates to work equally well with classes and built-in/intrinsic types. Operator overloading allows C/C++ operators to have user-defined meanings on user-defined types (classes). Overloaded operators are syntactic sugar for function calls: class ...

  14. C++ Operator Overloading (With Examples)

    Things to Remember in C++ Operator Overloading. 1. By default, operators = and & are already overloaded in C++. For example, we can directly use the = operator to copy objects of the same class. Here, we do not need to create an operator function. 2. We cannot change the precedence and associativity of operators using operator overloading. 3.

  15. Assignment operators

    Correct behavior. CWG 1527. C++11. for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator. removed user-defined assignment constraint. CWG 1538. C++11. E1 ={E2} was equivalent to E1 = T(E2) (T is the type of E1), this introduced a C-style cast.

  16. Mastering Operator Overloading: A Comprehensive Guide

    In Closing 🌈. Overall, mastering the art of operator overloading in C++ is like wielding a powerful magic wand in the world of programming. By understanding the basics, embracing best practices, exploring advanced techniques, and steering clear of common pitfalls, you can elevate your code to new heights of elegance and efficiency! 🚀🌟 Thank you for joining me on this enchanting ...

  17. operator overloading

    Overloaded operators. When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following: Expression. As member function.

  18. A centralized delay-sensitive hierarchical computation offloading in

    MEC (Multi-access Edge Computing) is vital in 5G and beyond (B5G) for reducing latency and enhancing network efficiency through local processing, crucial for real-time applications and improved security. This drives the adoption of advanced architectures like Fog Radio Access Network (F-RAN), which uses distributed resources from Radio Resource Heads (RRHs) or fog nodes to enable parallel ...

  19. c++

    This can result in changes done to one class object to affect all copies of this object. A solution to this can be to overload the = operator. Given the example below, with an attempt to create a dynamic array class, why does making changes to MyArray1 change MyArray2: Array Class: #include <iostream>.

  20. Operator Overloading in C++

    Prerequisite: Operator Overloading The assignment operator,"=", is the operator used for Assignment. It copies the right value into the left value. Assignment Operators are predefined to operate only on built-in Data types. Assignment operator overloading is binary operator overloading.Overloading assignment operator in C++ copies all values of one