Learn C++

21.12 — Overloading the assignment operator

The copy assignment operator (operator=) is used to copy values from one object to another already existing object .

Related content

As of C++11, C++ also supports “Move assignment”. We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .

Copy assignment vs Copy constructor

The purpose of the copy constructor and the copy assignment operator are almost equivalent -- both copy one object to another. However, the copy constructor initializes new objects, whereas the assignment operator replaces the contents of existing objects.

The difference between the copy constructor and the copy assignment operator causes a lot of confusion for new programmers, but it’s really not all that difficult. Summarizing:

  • If a new object has to be created before the copying can occur, the copy constructor is used (note: this includes passing or returning objects by value).
  • If a new object does not have to be created before the copying can occur, the assignment operator is used.

Overloading the assignment operator

Overloading the copy assignment operator (operator=) is fairly straightforward, with one specific caveat that we’ll get to. The copy assignment operator must be overloaded as a member function.

This prints:

This should all be pretty straightforward by now. Our overloaded operator= returns *this, so that we can chain multiple assignments together:

Issues due to self-assignment

Here’s where things start to get a little more interesting. C++ allows self-assignment:

This will call f1.operator=(f1), and under the simplistic implementation above, all of the members will be assigned to themselves. In this particular example, the self-assignment causes each member to be assigned to itself, which has no overall impact, other than wasting time. In most cases, a self-assignment doesn’t need to do anything at all!

However, in cases where an assignment operator needs to dynamically assign memory, self-assignment can actually be dangerous:

First, run the program as it is. You’ll see that the program prints “Alex” as it should.

Now run the following program:

You’ll probably get garbage output. What happened?

Consider what happens in the overloaded operator= when the implicit object AND the passed in parameter (str) are both variable alex. In this case, m_data is the same as str.m_data. The first thing that happens is that the function checks to see if the implicit object already has a string. If so, it needs to delete it, so we don’t end up with a memory leak. In this case, m_data is allocated, so the function deletes m_data. But because str is the same as *this, the string that we wanted to copy has been deleted and m_data (and str.m_data) are dangling.

Later on, we allocate new memory to m_data (and str.m_data). So when we subsequently copy the data from str.m_data into m_data, we’re copying garbage, because str.m_data was never initialized.

Detecting and handling self-assignment

Fortunately, we can detect when self-assignment occurs. Here’s an updated implementation of our overloaded operator= for the MyString class:

By checking if the address of our implicit object is the same as the address of the object being passed in as a parameter, we can have our assignment operator just return immediately without doing any other work.

Because this is just a pointer comparison, it should be fast, and does not require operator== to be overloaded.

When not to handle self-assignment

Typically the self-assignment check is skipped for copy constructors. Because the object being copy constructed is newly created, the only case where the newly created object can be equal to the object being copied is when you try to initialize a newly defined object with itself:

In such cases, your compiler should warn you that c is an uninitialized variable.

Second, the self-assignment check may be omitted in classes that can naturally handle self-assignment. Consider this Fraction class assignment operator that has a self-assignment guard:

If the self-assignment guard did not exist, this function would still operate correctly during a self-assignment (because all of the operations done by the function can handle self-assignment properly).

Because self-assignment is a rare event, some prominent C++ gurus recommend omitting the self-assignment guard even in classes that would benefit from it. We do not recommend this, as we believe it’s a better practice to code defensively and then selectively optimize later.

The copy and swap idiom

A better way to handle self-assignment issues is via what’s called the copy and swap idiom. There’s a great writeup of how this idiom works on Stack Overflow .

The implicit copy assignment operator

Unlike other operators, the compiler will provide an implicit public copy assignment operator for your class if you do not provide a user-defined one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).

Just like other constructors and operators, you can prevent assignments from being made by making your copy assignment operator private or using the delete keyword:

Note that if your class has const members, the compiler will instead define the implicit operator= as deleted. This is because const members can’t be assigned, so the compiler will assume your class should not be assignable.

If you want a class with const members to be assignable (for all members that aren’t const), you will need to explicitly overload operator= and manually assign each non-const member.

guest

operator overloading

Customizes the C++ operators for operands of user-defined types.

Overloaded operators are functions with special function names:

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:

Note: for overloading user-defined conversion functions , user-defined literals , allocation and deallocation see their respective articles.

Overloaded operators (but not the built-in operators) can be called using function notation:

Restrictions

  • The operators :: (scope resolution), . (member access), .* (member access through pointer to member), and ?: (ternary conditional) cannot be overloaded.
  • New operators such as ** , <> , or &| cannot be created.
  • The overloads of operators && and || lose short-circuit evaluation.
  • The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.
  • It is not possible to change the precedence, grouping, or number of operands of operators.

Canonical implementations

Other than the restrictions above, the language puts no other constraints on what the overloaded operators do, or on the return type (it does not participate in overload resolution), but in general, overloaded operators are expected to behave as similar as possible to the built-in operators: operator + is expected to add, rather than multiply its arguments, operator = is expected to assign, etc. The related operators are expected to behave similarly ( operator + and operator + = do the same addition-like operation). The return types are limited by the expressions in which the operator is expected to be used: for example, assignment operators return by reference to make it possible to write a = b = c = d , because the built-in operators allow that.

Commonly overloaded operators have the following typical, canonical forms: [1]

Assignment operator

The assignment operator ( operator = ) has special properties: see copy assignment and move assignment for details.

The canonical copy-assignment operator is expected to perform no action on self-assignment , and to return the lhs by reference:

The canonical move assignment is expected to leave the moved-from object in valid state (that is, a state with class invariants intact), and either do nothing or at least leave the object in a valid state on self-assignment, and return the lhs by reference to non-const, and be noexcept:

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 depending on the value category of the argument), swaps with the parameter, and lets the destructor clean it up.

This form automatically provides strong exception guarantee , but prohibits resource reuse.

Stream extraction and insertion

The overloads of operator>> and operator<< that take a std:: istream & or std:: ostream & as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument ( b in a@b ), they must be implemented as non-members.

These operators are sometimes implemented as friend functions .

Function call operator

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

Increment and decrement

When the postfix increment and decrement appear in an expression, the corresponding user-defined function ( operator ++ or operator -- ) is called with an integer argument 0 . Typically, it is implemented as T operator ++ ( int ) , where the argument is ignored. The postfix increment and decrement operator is usually implemented in terms of the prefix version:

Although canonical form of pre-increment/pre-decrement returns a reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value.

Binary arithmetic operators

Binary operators are typically implemented as non-members to maintain symmetry (for example, when adding a complex number and an integer, if operator+ is a member function of the complex type, then only complex + integer would compile, and not integer + complex ). Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments:

Relational operators

Standard algorithms such as std:: sort and containers such as std:: set expect operator < to be defined, by default, for the user-provided types, and expect it to implement strict weak ordering (thus satisfying the Compare requirements). An idiomatic way to implement strict weak ordering for a structure is to use lexicographical comparison provided by std::tie :

Typically, once operator < is provided, the other relational operators are implemented in terms of operator < .

Likewise, the inequality operator is typically implemented in terms of operator == :

When three-way comparison (such as std::memcmp or std::string::compare ) is provided, all six relational operators may be expressed through that:

Array subscript operator

User-defined classes that provide array-like access that allows both reading and writing typically define two overloads for operator [ ] : const and non-const variants:

If the value type is known to be a built-in type, the const variant should return by value.

Where direct access to the elements of the container is not wanted or not possible or distinguishing between lvalue c [ i ] = v ; and rvalue v = c [ i ] ; usage, operator[] may return a proxy. see for example std::bitset::operator[] .

To provide multidimensional array access semantics, e.g. to implement a 3D array access a [ i ] [ j ] [ k ] = x ; , operator[] has to return a reference to a 2D plane, which has to have its own operator[] which returns a reference to a 1D row, which has to have operator[] which returns a reference to the element. To avoid this complexity, some libraries opt for overloading operator ( ) instead, so that 3D access expressions have the Fortran-like syntax a ( i, j, k ) = x ;

Bitwise arithmetic operators

User-defined classes and enumerations that implement the requirements of BitmaskType are required to overload the bitwise arithmetic operators operator & , operator | , operator ^ , operator~ , operator & = , operator | = , and operator ^ = , and may optionally overload the shift operators operator << operator >> , operator >>= , and operator <<= . The canonical implementations usually follow the pattern for binary arithmetic operators described above.

Boolean negation operator

The operator operator ! is commonly overloaded by the user-defined classes that are intended to be used in boolean contexts. Such classes also provide a user-defined conversion function explicit operator bool ( ) (see std::basic_ios for the standard library example), and the expected behavior of operator ! is to return the value opposite of operator bool .

Rarely overloaded operators

The following operators are rarely overloaded:

  • The address-of operator, operator & . If the unary & is applied to an lvalue of incomplete type and the complete type declares an overloaded operator & , the behavior is undefined (until C++11) it is unspecified whether the operator has the built-in meaning or the operator function is called (since C++11) . Because this operator may be overloaded, generic libraries use std::addressof to obtain addresses of objects of user-defined types. The best known example of a canonical overloaded operator& is the Microsoft class CComPtr . An example of its use in EDSL can be found in boost.spirit .
  • The boolean logic operators, operator && and operator || . Unlike the built-in versions, the overloads cannot implement short-circuit evaluation. Also unlike the built-in versions, they do not sequence their left operand before the right one. (until C++17) In the standard library, these operators are only overloaded for std::valarray .
  • The comma operator, operator, . Unlike the built-in version, the overloads do not sequence their left operand before the right one. (until C++17) Because this operator may be overloaded, generic libraries use expressions such as a, void ( ) ,b instead of a,b to sequence execution of expressions of user-defined types. The boost library uses operator, in boost.assign , boost.spirit , and other libraries. The database access library SOCI also overloads operator, .
  • The member access through pointer to member operator - > * . There are no specific downsides to overloading this operator, but it is rarely used in practice. It was suggested that it could be part of smart pointer interface , and in fact is used in that capacity by actors in boost.phoenix . It is more common in EDSLs such as cpp.react .

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

  • Operator precedence
  • Alternative operator syntax
  • ↑ Operator Overloading on StackOverflow C++ FAQ

operator overloading

Customizes the C++ operators for operands of user-defined types.

[ edit ] Syntax

Overloaded operators are functions with special function names:

[ edit ] 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:

Note: for overloading user-defined conversion functions , user-defined literals , allocation and deallocation see their respective articles.

Overloaded operators (but not the built-in operators) can be called using function notation:

[ edit ] Restrictions

  • The operators :: (scope resolution), . (member access), .* (member access through pointer to member), and ?: (ternary conditional) cannot be overloaded
  • New operators such as ** , <> , or &| cannot be created
  • The overloads of operators && , || , and , (comma) lose their special properties: short-circuit evaluation and sequencing .

[ edit ] Canonical implementations

The language puts no restrictions on what the overloaded operators do, or on the return type (it does not participate in overload resolution), but in general, overloaded operators are expected to behave as similar as possible to the built-in operators: operator + is expected to add, rather than multiply its arguments, operator = is expected to assign, etc. The related operators are expected to behave similarly ( operator + and operator + = do the same addition-like operation). The return types are limited by the expressions in which the operator is expected to be used: for example, assignment operators return by reference to make it possible to write a = b = c = d , because the built-in operators allow that. Commonly overloaded operators have the following typical, canonical forms: [1]

[ edit ] Assignment operator

The assignment operator ( operator = ) has special properties: see copy assignment and move_assignment for details. To summarize, the canonical "universal assignment operator" implementation is

When there are resources that can be reused in assignment, for example, if the class owns a heap-allocated array, then copy-assignment between arrays of the same size can avoid allocation and deallocation:

[ edit ] Stream extraction and insertion

The overloads of operator>> and operator<< that take a std:: istream & or std:: ostream & as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument ( b in a@b ), they must be implemented as non-members.

These operators are sometimes implemented as friend functions .

[ edit ] Function call operator

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

[ edit ] Increment and decrement

When the postfix increment and decrement appear in an expression, the corresponding user-defined function ( operator ++ or operator -- ) is called with an integer argument 0 . Typically, it is implemented as T operator ++ ( int ) , where the argument is ignored. The postfix increment and decrement operator is usually implemented in terms of the prefix version:

Although canonical form of preincrement/predecrement returns a reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value.

[ edit ] Binary arithmetic operators

Binary operators are typically implemented as non-members to maintain symmetry (for example, when adding a complex number and an integer, if operator+ is a member function of the complex type, then only complex + integer would compile, and not integer + complex ). Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments:

[ edit ] Relational operators

Standard algorithms such as std:: sort and containers such as std:: set expect operator < to be defined, by default, for the user-provided types. Typically, operator < is provided and the other relational operators are implemented in terms of operator < .

Likewise, the inequality operator is typically implemented in terms of operator == :

[ edit ] Array subscript operator

User-defined classes that provide array-like access typically define two overloads for operator [ ] : one which can be called in rvalue context such as x = a [ i ] ; , and one which can be used in lvalue context, such as a [ i ] = x ; .

To provide multidimensional array access semantics, e.g. to implement a 3D array access a [ i ] [ j ] [ k ] = x ; , operator[] has to return a reference to a 2D plane, which has to have its own operator[] which returns a reference to a 1D row, which has to have operator[] which returns a reference to the element. To avoid this complexity, some libraries opt for overloading operator ( ) instead, so that 3D access expressions have the Fortran-like syntax a ( i,j,k ) = x ;

[ edit ] Example

[ edit ] see also.

  • Operator precedence
  • Alternative operator syntax

[ edit ] References

  • ↑ Operator Overloading on StackOverflow C++ FAQ

Overloading assignments (C++ only)

  • Copy assignment operators (C++ only)
  • Assignment operators

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

93 Top Machine Learning Projects in Python with Source Code for Your Next Project

Top Machine Learning Projects in Python with Source Code for Your Next Project

86 Machine Learning Projects for Final Year with Source Code: A Comprehensive Guide to Success

Machine Learning Projects for Final Year with Source Code: A Comprehensive Guide to Success

87 Top 10 Machine Learning Projects for Students to Excel in Machine Learning Project

Top 10 Machine Learning Projects for Students to Excel in Machine Learning Project

82 Top Machine Learning Projects for Students: A Compilation of Exciting ML Projects to Boost Your Skills in 2022 Project

Top Machine Learning Projects for Students: A Compilation of Exciting ML Projects to Boost Your Skills in 2022 Project

75 Top Machine Learning Projects on GitHub for Deep Learning Enthusiasts - Dive into Exciting Project Ideas Now!

Top Machine Learning Projects on GitHub for Deep Learning Enthusiasts – Dive into Exciting Project Ideas Now!

Privacy overview.

Sign in to your account

Username or Email Address

Remember Me

cppreference.com

Overload resolution.

In order to compile a function call, the compiler must first perform name lookup , which, for functions, may involve argument-dependent lookup , and for function templates may be followed by template argument deduction .

If the name refers to more than one entity, it is said to be overloaded , and the compiler must determine which overload to call. In simple terms, the overload whose parameters match the arguments most closely is the one that is called.

In detail, overload resolution proceeds through the following steps:

  • Building the set of candidate functions .
  • Trimming the set to only viable functions .
  • Analyzing the set to determine the single best viable function (this may involve ranking of implicit conversion sequences ).

Besides function calls, overloaded function names may appear in several additional contexts, where different rules apply: see Address of an overloaded function .

If a function cannot be selected by overload resolution, it cannot be used (e.g. it is a templated entity with a failed constraint ).

[ edit ] Candidate functions

Before overload resolution begins, the functions selected by name lookup and template argument deduction are combined to form the set of candidate functions . The exact details depend on the context in which overload resolution takes place.

[ edit ] Call to a named function

If E in a function call expression E(args) names a set of overloaded functions and/or function templates (but not callable objects), the following rules are followed:

  • If the expression E has the form PA->B or A.B (where A has class type cv T), then B is looked up as a member function of T . The function declarations found by that lookup are the candidate functions. The argument list for the purpose of overload resolution has the implied object argument of type cv T.
  • If the expression E is a primary expression , the name is looked up following normal rules for function calls (which may involve ADL ). The function declarations found by this lookup are (due to the way lookup works) either:

[ edit ] Call to a class object

If E in a function call expression E(args) has class type cv T , then

  • The function-call operators of T are obtained by ordinary lookup of the name operator ( ) in the context of the expression (E).operator() , and every declaration found is added to the set of candidate functions.
  • For each non-explicit user-defined conversion function in T or in a base of T (unless hidden), whose cv-qualifiers are the same or greater than T 's cv-qualifiers, and where the conversion function converts to:
  • pointer-to-function
  • reference-to-pointer-to-function
  • reference-to-function

In any case, the argument list for the purpose of overload resolution is the argument list of the function call expression preceded by the implied object argument E (when matching against the surrogate function, the user-defined conversion will automatically convert the implied object argument to the first argument of the surrogate function).

[ edit ] Call to an overloaded operator

If at least one of the arguments to an operator in an expression has a class type or an enumeration type, both builtin operators and user-defined operator overloads participate in overload resolution, with the set of candidate functions selected as follows:

For a unary operator @ whose argument has type T1 (after removing cv-qualifications), or binary operator @ whose left operand has type T1 and right operand of type T2 (after removing cv-qualifications), the following sets of candidate functions are prepared:

The set of candidate functions to be submitted for overload resolution is a union of the sets above. The argument list for the purpose of overload resolution consists of the operands of the operator except for operator-> , where the second operand is not an argument for the function call (see member access operator ).

If the overload resolution selects a built-in candidate, the user-defined conversion sequence from an operand of class type is not allowed to have a second standard conversion sequence: the user-defined conversion function must give the expected operand type directly:

For operator, , the unary operator & , and operator - > , if there are no viable functions (see below) in the set of candidate functions, then the operator is reinterpreted as a built-in.

[ edit ] Initialization by constructor

When an object of class type is direct-initialized or default-initialized outside a copy-initialization context, the candidate functions are all constructors of the class being initialized. The argument list is the expression list of the initializer.

When an object of class type is copy-initialized from an object of the same or derived class type, or default-initialized in a copy-initialization context, the candidate functions are all converting constructors of the class being initialized. The argument list is the expression of the initializer.

[ edit ] Copy-initialization by conversion

If copy-initialization of an object of class type requires that a user-defined conversion is called to convert the initializer expression of type cv S to the type cv T of the object being initialized, the following functions are candidate functions:

  • all converting constructors of T
  • the non-explicit conversion functions from S and its base classes (unless hidden) to T or class derived from T or a reference to such. If this copy-initialization is part of the direct-initialization sequence of cv T (initializing a reference to be bound to the first parameter of a constructor that takes a reference to cv T ), then explicit conversion functions are also considered.

Either way, the argument list for the purpose of overload resolution consists of a single argument which is the initializer expression, which will be compared against the first argument of the constructor or against the implicit object argument of the conversion function.

[ edit ] Non-class initialization by conversion

When initialization of an object of non-class type cv1 T requires a user-defined conversion function to convert from an initializer expression of class type cv S , the following functions are candidates:

  • the non-explicit user-defined conversion functions of S and its base classes (unless hidden) that produce type T or a type convertible to T by a standard conversion sequence , or a reference to such type. cv qualifiers on the returned type are ignored for the purpose of selecting candidate functions.
  • if this is direct-initialization , the explicit user-defined conversion functions of S and its base classes (unless hidden) that produce type T or a type convertible to T by a qualification conversion , or a reference to such type, are also considered.

Either way, the argument list for the purpose of overload resolution consists of a single argument which is the initializer expression, which will be compared against the implicit object argument of the conversion function.

[ edit ] Reference initialization by conversion

During reference initialization , where the reference to cv1 T is bound to the lvalue or rvalue result of a conversion from the initializer expression from the class type cv2 S , the following functions are selected for the candidate set:

  • The non-explicit user-defined conversion functions of S and its base classes (unless hidden) to the type
  • (when initializing lvalue reference or rvalue reference to function) lvalue reference to cv2 T2
  • (when initializing rvalue reference or lvalue reference to function) cv2 T2 or rvalue reference to cv2 T2
  • For direct initialization, the explicit user-defined conversion functions are also considered if T2 is the same type as T or can be converted to type T with a qualification conversion.

[ edit ] List-initialization

When an object of non-aggregate class type T is list-initialized , two-phase overload resolution takes place.

  • at phase 1, the candidate functions are all initializer-list constructors of T and the argument list for the purpose of overload resolution consists of a single initializer list argument
  • if overload resolution fails at phase 1, phase 2 is entered, where the candidate functions are all constructors of T and the argument list for the purpose of overload resolution consists of the individual elements of the initializer list.

If the initializer list is empty and T has a default constructor, phase 1 is skipped.

In copy-list-initialization, if phase 2 selects an explicit constructor, the initialization is ill-formed (as opposed to all over copy-initializations where explicit constructors are not even considered).

[ edit ] Additional rules for function template candidates

If name lookup found a function template, template argument deduction and checking of any explicit template arguments are performed to find the template argument values (if any) that can be used in this case:

  • If both succeeds, the template arguments are used to synthesize declarations of the corresponding function template specializations, which are added to the candidate set, and such specializations are treated just like non-template functions except where specified otherwise in the tie-breaker rules below.
  • If argument deduction fails or the synthesized function template specialization would be ill-formed, no such function is added to the candidate set (see SFINAE ).

If a name refers to one or more function templates and also to a set of overloaded non-template functions, those functions and the specializations generated from the templates are all candidates.

See function template overloading for further detail.

[ edit ] Additional rules for constructor candidates

[ edit ] additional rules for member function candidates.

If any candidate function is a member function (static or non-static) that does not have an explicit object parameter (since C++23) , but not a constructor, it is treated as if it has an extra parameter ( implicit object parameter ) which represents the object for which they are called and appears before the first of the actual parameters.

Similarly, the object on which a member function is being called is prepended to the argument list as the implied object argument .

For member functions of class X , the type of the implicit object parameter is affected by cv-qualifications and ref-qualifications of the member function as described in member functions .

The user-defined conversion functions are considered to be members of the implied object argument for the purpose of determining the type of the implicit object parameter .

The member functions introduced by a using-declaration into a derived class are considered to be members of the derived class for the purpose of defining the type of the implicit object parameter .

For the rest of overload resolution, the implied object argument is indistinguishable from other arguments, but the following special rules apply to the implicit object parameter :

[ edit ] Viable functions

Given the set of candidate functions, constructed as described above, the next step of overload resolution is examining arguments and parameters to reduce the set to the set of viable functions

To be included in the set of viable functions, the candidate function must satisfy the following:

User-defined conversions (both converting constructors and user-defined conversion functions) are prohibited from taking part in implicit conversion sequence where it would make it possible to apply more than one user-defined conversion. Specifically, they are not considered if the target of the conversion is the first parameter of a constructor or the implicit object parameter of a user-defined conversion function, and that constructor/user-defined conversion is a candidate for

  • copy-initialization of a class by user-defined conversion ,
  • initialization of a non-class type by a conversion function ,
  • initialization by conversion function for direct reference binding ,
  • initialization by constructor during the second (direct-initialization) step of class copy-initialization ,

[ edit ] Best viable function

For each pair of viable function F1 and F2 , the implicit conversion sequences from the i -th argument to i -th parameter are ranked to determine which one is better (except the first argument, the implicit object argument for static member functions has no effect on the ranking)

F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and

These pair-wise comparisons are applied to all viable functions. If exactly one viable function is better than all others, overload resolution succeeds and this function is called. Otherwise, compilation fails.

If the best viable function resolves to a function for which multiple declarations were found, and if any two of these declarations inhabit different scopes and specify a default argument that made the function viable, the program is ill-formed.

[ edit ] Ranking of implicit conversion sequences

The argument-parameter implicit conversion sequences considered by overload resolution correspond to implicit conversions used in copy initialization (for non-reference parameters), except that when considering conversion to the implicit object parameter or to the left-hand side of assignment operator, conversions that create temporary objects are not considered. When the parameter is the implicit object parameter of a static member function, the implicit conversion sequence is a standard conversion sequence that is neither better nor worse than any other standard conversion sequence. (since C++23)

Each type of standard conversion sequence is assigned one of three ranks:

The rank of the standard conversion sequence is the worst of the ranks of the standard conversions it holds (there may be up to three conversions )

Binding of a reference parameter directly to the argument expression is either Identity or a derived-to-base Conversion:

Since ranking of conversion sequences operates with types and value categories only, a bit field can bind to a reference argument for the purpose of ranking, but if that function gets selected, it will be ill-formed.

If two conversion sequences are indistinguishable because they have the same rank, the following additional rules apply:

Ambiguous conversion sequences are ranked as user-defined conversion sequences because multiple conversion sequences for an argument can exist only if they involve different user-defined conversions:

[ edit ] Implicit conversion sequence in list-initialization

In list initialization , the argument is a braced-init-list , which isn't an expression, so the implicit conversion sequence into the parameter type for the purpose of overload resolution is decided by the following special rules:

  • If the parameter type is some aggregate X and the initializer list consists of exactly one element of same or derived class (possibly cv-qualified), the implicit conversion sequence is the one required to convert the element to the parameter type.
  • Otherwise, if the parameter type is a reference to character array and the initializer list has a single element that is an appropriately-typed string literal, the implicit conversion sequence is the identity conversion.
  • Otherwise, if the parameter type is std:: initializer_list < X > , and there is a non-narrowing implicit conversion from every element of the initializer list to X , the implicit conversion sequence for the purpose of overload resolution is the worst conversion necessary. If the braced-init-list is empty, the conversion sequence is the identity conversion.
  • Otherwise, if the parameter type is "array of N T" (this only happens for references to arrays), the initializer list must have N or less elements, and the worst implicit conversion necessary to convert every element of the list (or the empty pair of braces {} if the list is shorter than N) to T is the one used.
  • Otherwise, if the parameter type is a non-aggregate class type X , overload resolution picks the constructor C of X to initialize from the argument initializer list
  • If C is not an initializer-list constructor and the initializer list has a single element of possibly cv-qualified X, the implicit conversion sequence has Exact Match rank. If the initializer list has a single element of possibly cv-qualified type derived from X, the implicit conversion sequence has Conversion rank. (note the difference from aggregates: aggregates initialize directly from single-element init lists before considering aggregate initialization , non-aggregates consider initializer_list constructors before any other constructors)
  • otherwise, the implicit conversion sequence is a user-defined conversion sequence with the second standard conversion sequence an identity conversion.

If multiple constructors are viable but none is better than the others, the implicit conversion sequence is the ambiguous conversion sequence.

  • Otherwise, if the parameter type is an aggregate which can be initialized from the initializer list according by aggregate initialization , the implicit conversion sequence is a user-defined conversion sequence with the second standard conversion sequence an identity conversion.
  • Otherwise, if the parameter is a reference, reference initialization rules apply
  • Otherwise, if the parameter type is not a class and the initializer list has one element, the implicit conversion sequence is the one required to convert the element to the parameter type
  • Otherwise, if the parameter type is not a class type and if the initializer list has no elements, the implicit conversion sequence is the identity conversion.

[ edit ] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

  • ↑ The type of the of the first parameter of a built-in assignment operator is “lvalue reference to possibly volatile-qualified T ”. References of this type cannot bould to a temporary.

[ edit ] References

  • C++23 standard (ISO/IEC 14882:2023):
  • 12.2 Overload resolution [over.match]
  • C++20 standard (ISO/IEC 14882:2020):
  • 12.4 Overload resolution [over.match]
  • C++17 standard (ISO/IEC 14882:2017):
  • 16.3 Overload resolution [over.match]
  • C++14 standard (ISO/IEC 14882:2014):
  • 13.3 Overload resolution [over.match]
  • C++11 standard (ISO/IEC 14882:2011):
  • C++03 standard (ISO/IEC 14882:2003):

[ edit ] See also

  • Name lookup
  • Argument-dependent lookup
  • Template argument deduction
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 26 January 2024, at 01:37.
  • This page has been accessed 414,806 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

  • 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

  • C++ Programming Language

C++ Overview

  • Introduction to C++ Programming Language
  • Features of C++
  • History of C++
  • Interesting Facts about C++
  • Setting up C++ Development Environment
  • Difference between C and C++
  • Writing First C++ Program - Hello World Example
  • C++ Basic Syntax
  • C++ Comments
  • Tokens in C
  • C++ Keywords
  • Difference between Keyword and Identifier

C++ Variables and Constants

  • C++ Variables
  • Constants in C
  • Scope of Variables in C++
  • Storage Classes in C++ with Examples
  • Static Keyword in C++

C++ Data Types and Literals

  • C++ Data Types
  • Literals in C
  • Derived Data Types in C++
  • User Defined Data Types in C++
  • Data Type Ranges and their macros in C++
  • C++ Type Modifiers
  • Type Conversion in C++
  • Casting Operators in C++

C++ Operators

  • Operators in C++
  • C++ Arithmetic Operators
  • Unary operators in C
  • Bitwise Operators in C
  • Assignment Operators in C
  • C++ sizeof Operator
  • Scope resolution operator in C++

C++ Input/Output

  • Basic Input / Output in C++
  • cout in C++
  • cerr - Standard Error Stream Object in C++
  • Manipulators in C++ with Examples

C++ Control Statements

  • Decision Making in C (if , if..else, Nested if, if-else-if )
  • C++ if Statement
  • C++ if else Statement
  • C++ if else if Ladder
  • Switch Statement in C++
  • Jump statements in C++
  • for Loop in C++
  • Range-based for loop in C++
  • C++ While Loop
  • C++ Do/While Loop

C++ Functions

  • Functions in C++
  • return statement in C++ with Examples
  • Parameter Passing Techniques in C
  • Difference Between Call by Value and Call by Reference in C
  • Default Arguments in C++
  • Inline Functions in C++
  • Lambda expression in C++

C++ Pointers and References

  • Pointers and References in C++
  • C++ Pointers
  • Dangling, Void , Null and Wild Pointers in C
  • Applications of Pointers in C
  • Understanding nullptr in C++
  • References in C++
  • Can References Refer to Invalid Location in C++?
  • Pointers vs References in C++
  • Passing By Pointer vs Passing By Reference in C++
  • When do we pass arguments by pointer?
  • Variable Length Arrays (VLAs) in C
  • Pointer to an Array | Array Pointer
  • How to print size of array parameter in C++?
  • Pass Array to Functions in C
  • What is Array Decay in C++? How can it be prevented?

C++ Strings

  • Strings in C++
  • std::string class in C++
  • Array of Strings in C++ - 5 Different Ways to Create
  • String Concatenation in C++
  • Tokenizing a string in C++
  • Substring in C++

C++ Structures and Unions

  • Structures, Unions and Enumerations in C++
  • Structures in C++
  • C++ - Pointer to Structure
  • Self Referential Structures
  • Difference Between C Structures and C++ Structures
  • Enumeration in C++
  • typedef in C++
  • Array of Structures vs Array within a Structure in C

C++ Dynamic Memory Management

  • Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()
  • new and delete Operators in C++ For Dynamic Memory
  • new vs malloc() and free() vs delete in C++
  • What is Memory Leak? How can we avoid?
  • Difference between Static and Dynamic Memory Allocation in C

C++ Object-Oriented Programming

  • Object Oriented Programming in C++
  • Access Modifiers in C++
  • Friend Class and Function in C++
  • Constructors in C++
  • Default Constructors in C++
  • Copy Constructor in C++
  • Destructors in C++
  • Private Destructor in C++
  • When is a Copy Constructor Called in C++?
  • Shallow Copy and Deep Copy in C++
  • When Should We Write Our Own Copy Constructor in C++?
  • Does C++ compiler create default constructor when we write our own?
  • C++ Static Data Members
  • Static Member Function in C++
  • 'this' pointer in C++
  • Scope Resolution Operator vs this pointer in C++
  • Local Classes in C++
  • Nested Classes in C++
  • Enum Classes in C++ and Their Advantage over Enum DataType
  • Difference Between Structure and Class in C++
  • Why C++ is partially Object Oriented Language?

C++ Encapsulation and Abstraction

  • Encapsulation in C++
  • Abstraction in C++
  • Difference between Abstraction and Encapsulation in C++
  • Function Overriding in C++
  • Virtual Functions and Runtime Polymorphism in C++
  • Difference between Inheritance and Polymorphism
  • Function Overloading in C++
  • Constructor Overloading in C++
  • Functions that cannot be overloaded in C++
  • Function overloading and const keyword
  • Function Overloading and Return Type in C++
  • Function Overloading and float in C++
  • C++ Function Overloading and Default Arguments
  • Can main() be overloaded in C++?
  • Function Overloading vs Function Overriding in C++
  • Advantages and Disadvantages of Function Overloading in C++

C++ Operator Overloading

Operator overloading in c++.

  • Types of Operator Overloading in C++
  • Functors in C++
  • What are the Operators that Can be and Cannot be Overloaded in C++?
  • Inheritance in C++
  • C++ Inheritance Access
  • Multiple Inheritance in C++
  • C++ Hierarchical Inheritance
  • C++ Multilevel Inheritance
  • Constructor in Multiple Inheritance in C++
  • Inheritance and Friendship in C++
  • Does overloading work with Inheritance?

C++ Virtual Functions

  • Virtual Function in C++
  • Virtual Functions in Derived Classes in C++
  • Default Arguments and Virtual Function in C++
  • Can Virtual Functions be Inlined in C++?
  • Virtual Destructor
  • Advanced C++ | Virtual Constructor
  • Advanced C++ | Virtual Copy Constructor
  • Pure Virtual Functions and Abstract Classes in C++
  • Pure Virtual Destructor in C++
  • Can Static Functions Be Virtual in C++?
  • RTTI (Run-Time Type Information) in C++
  • Can Virtual Functions be Private in C++?

C++ Exception Handling

  • Exception Handling in C++
  • Exception Handling using classes in C++
  • Stack Unwinding in C++
  • User-defined Custom Exception with class in C++

C++ Files and Streams

  • File Handling through C++ Classes
  • I/O Redirection in C++
  • Templates in C++ with Examples
  • Template Specialization in C++
  • Using Keyword in C++ STL

C++ Standard Template Library (STL)

  • The C++ Standard Template Library (STL)
  • Containers in C++ STL (Standard Template Library)
  • Introduction to Iterators in C++
  • Algorithm Library | C++ Magicians STL Algorithm

C++ Preprocessors

  • C Preprocessors
  • C Preprocessor Directives
  • #include in C
  • Difference between Preprocessor Directives and Function Templates in C++

C++ Namespace

  • Namespace in C++ | Set 1 (Introduction)
  • namespace in C++ | Set 2 (Extending namespace and Unnamed namespace)
  • Namespace in C++ | Set 3 (Accessing, creating header, nesting and aliasing)
  • C++ Inline Namespaces and Usage of the "using" Directive Inside Namespaces

Advanced C++

  • Multithreading in C++
  • Smart Pointers in C++
  • auto_ptr vs unique_ptr vs shared_ptr vs weak_ptr in C++
  • Type of 'this' Pointer in C++
  • "delete this" in C++
  • Passing a Function as a Parameter in C++
  • Signal Handling in C++
  • Generics in C++
  • Difference between C++ and Objective C
  • Write a C program that won't compile in C++
  • Write a program that produces different results in C and C++
  • How does 'void*' differ in C and C++?
  • Type Difference of Character Literals in C and C++
  • Cin-Cout vs Scanf-Printf

C++ vs Java

  • Similarities and Difference between Java and C++
  • Comparison of Inheritance in C++ and Java
  • How Does Default Virtual Behavior Differ in C++ and Java?
  • Comparison of Exception Handling in C++ and Java
  • Foreach in C++ and Java
  • Templates in C++ vs Generics in Java
  • Floating Point Operations & Associativity in C, C++ and Java

Competitive Programming in C++

  • Competitive Programming - A Complete Guide
  • C++ tricks for competitive programming (for C++ 11)
  • Writing C/C++ code efficiently in Competitive programming
  • Why C++ is best for Competitive Programming?
  • Test Case Generation | Set 1 (Random Numbers, Arrays and Matrices)
  • Fast I/O for Competitive Programming
  • Setting up Sublime Text for C++ Competitive Programming Environment
  • How to setup Competitive Programming in Visual Studio Code for C++
  • Which C++ libraries are useful for competitive programming?
  • Common mistakes to be avoided in Competitive Programming in C++ | Beginners
  • C++ Interview Questions and Answers (2024)
  • Top C++ STL Interview Questions and Answers
  • 30 OOPs Interview Questions and Answers (2024)
  • Top C++ Exception Handling Interview Questions and Answers
  • C++ Programming Examples

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++ 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.

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:

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++

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. 

Can We Overload All Operators?  

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

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 (: 🙂 Member selection operator                              Member selection through  *

Pointer to a member variable

  • Conditional operator (? 🙂
  • Sizeof operator  sizeof()

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:

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. 

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

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:  

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. 

Quiz on Operator Overloading

Please Login to comment...

Similar reads.

  • cpp-operator-overloading
  • cpp-overloading

advertisewithusBannerImg

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

  2. Overloading C++ "Assignment Operator =" with Example

    c overload assignment operator

  3. Matrix addition using operator overloading in c

    c overload assignment operator

  4. Assignment Operator Overloading In C++

    c overload assignment operator

  5. Overloading Pre and Post Increment Operator in C++

    c overload assignment operator

  6. Overloading assignment operator in C++

    c overload assignment operator

VIDEO

  1. Relational Operator Overloading in C++ [Hindi]

  2. Overloading +

  3. Assignment operator overloading in c++

  4. Operator Overloading in C++

  5. Assignment Operator Overloading In C++

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

COMMENTS

  1. assignment operator overloading in c++

    There are no problems with the second version of the assignment operator. In fact, that is the standard way for an assignment operator. Edit: Note that I am referring to the return type of the assignment operator, not to the implementation itself. As has been pointed out in comments, the implementation itself is another issue.

  2. 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.

  3. 21.12

    21.12 — Overloading the assignment operator. Alex November 27, 2023. 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 .

  4. operator overloading

    The assignment operator (operator =) has special properties: ... user-defined classes that are intended to be used in boolean contexts could provide only operator bool and need not overload operator!. (since C++11) Rarely overloaded operators. The following operators are rarely overloaded:

  5. Assignment operators

    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. it is equivalent to E1 = T{E2}

  6. c++

    The difference between overloading by friend function and overloading by member function is that the calling object must be the first operand in overloading by member function, while there is no restriction in overloading by friend function.This is the reason behind the standard. Similarly, some other operators requiring the first operand to be the calling function must be overloaded using ...

  7. Copy assignment operator

    Triviality of eligible copy assignment operators determines whether the class is a trivially copyable type. [] NoteIf both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move), and selects the copy assignment if the argument is an ...

  8. 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 ...

  9. 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.

  10. Mastering Operator Overloads: A Comprehensive Guide

    Code Explanation: The program defines a class ComplexNumber to represent complex numbers and provide operator overloads for common mathematical operations. The __init__ method initializes each complex number with a real and an imaginary component. The __repr__ method allows us to print complex number objects in a way that's human-readable ...

  11. Overloading assignments (C++ only)

    Overloading assignments (C++ only) You overload the assignment operator, operator=, with a nonstatic member function that has only one parameter. You cannot declare an overloaded assignment operator that is a nonmember function. The following example shows how you can overload the assignment operator for a particular class: struct X {. int data;

  12. 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 ...

  13. 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 ...

  14. 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 ...

  15. 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.

  16. Overloading assignment operator in C#

    There is already a special instance of overloading = in place that the designers deemed ok: property setters. Let X be a property of foo. In foo.X = 3, the = symbol is replaced by the compiler by a call to foo.set_X(3). You can already define a public static T op_Assign(ref T assigned, T assignee) method. All that is left is for the compiler to ...

  17. C++ : Overload Assignment (=) operator :: AlgoTree

    C++ : Overload Assignment (=) operator. Just like a copy constructor the compiler provides a default free implementation of the assignment operator for a class. The compiler provided assignment operator implementation does a member-wise copy of the data members. This is often referred to as shallow copying. Overload '=' (assignment) operator.

  18. When should we write our own assignment operator in C++?

    1) Do not allow assignment of one object to other object. We can create our own dummy assignment operator and make it private. 2) Write your own assignment operator that does deep copy. Same is true for Copy Constructor. Following is an example of overloading assignment operator for the above class. #include<iostream>.

  19. Assignment Operator Overload in c++

    An overloaded assignment operator should look like this: Complex &Complex::operator=(const Complex& rhs) {. real = rhs.real; imaginary = rhs.imaginary; return *this; }; You should also note, that if you overload the assignment operator you should overload the copy constructor for Complex in the same manner:

  20. c++

    4. 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.

  21. 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. ... Assignment Operator: Compiler automatically creates a default assignment operator with every class. The default assignment operator does assign all members of the right ...