14.1: Operator Overload
- Page ID
- 29118
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)What is overloading in C++?
Creating two or more objects that have the same name but are different in how they operate is known as overloading.
In C++, we can overload:
- Operators
- Methods - often referred to as function overloading
Types of overloading
Operator Overloading in C++
We will discuss operator overloading first, then in the next section we will discuss function overloading.
In C++, we can make operators to work for user defined classes. This means C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading.
For example, we can overload an operator ‘+’ in a class like String so that we can concatenate two strings by just using + as in the following example code snippet
String firstName = "Pat"; String lastName = "McClanahan"; String fullName; // The + operator understands it is working on Strings // so it concatenates them instead of attempting to add them fullName = firstName + lastName
Other example classes where arithmetic operators may be overloaded are Complex Number, Fractional Number, Big Integer, etc.
What is the difference between operator functions and normal functions?
Operators methods are same as normal methods. The only differences are, name of an operator function is always operator keyword followed by symbol of operator and operator functions are called when the corresponding operator is used.
Following is an example of global operator function.
#include <iostream> using namespace std; class NewOp { private: int myVal; public: void getvalue() { // The cin puts the entered value in the objects myVal variable. cin>>myVal; } NewOp operator + (NewOp inObj) { NewOp opObj; // opObj is defined in this function // inObj is the argument passed in - it is the obj on the right of the operator // myVal is the class variable associated with the object to the left of the operator opObj.myVal = myVal + inObj.myVal; return opObj; } NewOp operator - (NewOp inObj) { NewOp opObj; // opObj is defined in this function // inObj is the argument passed in - it is the obj on the right of the operator // myVal is the class variable associated with the object to the left of the operator opObj.myVal = myVal - inObj.myVal; return opObj; } int display() { return myVal; } }; int main() { NewOp obj1, obj2, sum, sub; cout << "enter an integer value for obj1: "; obj1.getvalue(); cout << "Enter an integer value for obj2: "; obj2.getvalue(); sum = obj1 + obj2; sub = obj1 - obj2; cout<<"Addition result is = "<<sum.display()<<endl; cout<<"Subtraction result is = "<<sub.display()<<endl; return 0; }
In this code we overload the + and the - operator. One thing to notice: in the operator overload functions there is a single argument, this argument is the object TO THE RIGHT of the operator...so in this example the function argument is the obj2 object. The other value is picked up from that object's myVal variable - that is the object to the right of the operator, in out example this is obj1.
In case you are interested, the output from the sample code is:
enter an integer value for obj1: 10 Enter an integer value for obj2: 99 Addition result is = 109 Subtraction result is = -89
Can we overload all operators?
Almost all operators can be overloaded except few. Following is the list of operators that cannot be overloaded.
. (dot) :: ?: sizeof
Why can’t . (dot), ::, ?: and sizeof be overloaded?
See this for answers from Stroustrup (the creator of C++) himself.
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 right side to the left side and works fine most of the cases (this behavior is same as 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.
#include <iostream> using namespace std; class Fraction { private: int num, den; public: Fraction(int n, int d) { // constructor sets a numerator and a denominiator for the fraction num = n; den = d; } // conversion operator: return float value of fraction operator float() const { return float(num) / float(den); } }; int main() { Fraction frac(2, 5); float val = frac; cout << val; return 0; }
When the code executes the statement float val = frac; we create an instance of the conversion operator, which calls the float() method. This method takes the two integer values, num and den, which were created and assigned values what we create an instance of the Fraction class: Fraction frac(2,5); and using the system float conversion to convert them to floating point values and performs the division. This overloading does a different conversion than the system conversion method which simply changes an integer value into a floating value.
The output is the result of a simple division:
0.4
Adapted from:
"Operator Overloading in C++" by Shun Xian Cai, Geeks for Geeks is licensed under CC BY-SA 4.0