Operator_Overloading_( Member + Friend Function Behavior)
Operator_Overloading_( Member + Friend Function Behavior)
BRANCH : CE ( 24CEUOG121 )
BATCH : A2
ROLL NO, : 041
SUB : ADVANCED C++ PROGRAMMING CONCEPTS
FOCUS: OVERLOAD RESOLUTION | COMPILER BEHAVIOR
Q-1
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1), c2(2.2, 2.2), c3 ;
}
// error : more than one operator "+" matches
void print() { these operands
cout << re << " + j" << im << endl; c3 = c1 + c2;
}
c3.print();
// Without constant arguments (pass by reference)
Complex operator+( Complex &c2){ return 0;
cout << "Inside method : " ; }
return Complex(this->re+c2.re , this->im+c2.im);
}
};
Maulik N. Patoliya
Q-2
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// With constant arguments (pass by reference)
Complex operator+(const Complex &c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
output ?
// With constant arguments(pass by reference)
friend Complex operator+(const Complex &c1,const Complex &c2);
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// With constant arguments (pass by reference)
Complex operator+(const Complex &c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
};
Maulik N. Patoliya
Q-3
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// With constant arguments (pass by reference)
Complex operator+(const Complex &c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
output ?
// Without constant arguments(pass by reference)
friend Complex operator+( Complex &c1, Complex &c2);
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// With constant arguments (pass by reference)
Complex operator+(const Complex &c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
};
Maulik N. Patoliya
Why compiler call friend function instead of member function call ?
Checking Friend Function :
The friend function expects two non-const references: Complex& c1, Complex& c2.
Since c1 and c2 are both modifiable (not const), this match is perfect.
Conclusion :
The friend function is a better match due to the exact type match (Complex& arguments).
The member function requires an implicit conversion (modifying this to be const), which makes
it less preferable.
Maulik N. Patoliya
Q-4
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// Without constant arguments (pass by reference)
Complex operator+( Complex &c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
output ?
// With constant arguments(pass by reference)
friend Complex operator+(const Complex &c1,const Complex &c2);
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// Without constant arguments (pass by reference)
Complex operator+( Complex &c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
};
Maulik N. Patoliya
Error
Method Reason for Error or
Case Arguments Type Occurred Output
Used Success
?
Maulik N. Patoliya
Conclusion
Valid Conditions :
If both functions takes ( const reference ) const complex& , works fine and call member
function.
If one function (either member or friend ) takes ( const reference ) const complex&
and the other one takes ( non-const reference ) complex& , there is no ambiguity error
andoverloading works fine.
If member function has constant arguments and friend doesn’t have, then always
call friend function .
If friend function has constant arguments and member function doesn’t have,
then always call member function .
If the friend function is not defined , the member function alone works fine.
If the member function is not defined , the friend function alone works fine.
Maulik N. Patoliya
Invalid Conditions ( Causes Error ) :
If both the member and friend function take non-const reference , the compiler
cannot decide which one to call ( ambiguity error ).
Maulik N. Patoliya
Q-5
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-6
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
c3 = c1 + c2;
void print() { c3.print();
cout << re << " + j" << im << endl;
} return 0;
}
// With constant arguments (pass by value)
Complex operator+(const Complex c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}
output ?
// With constant arguments (pass by value)
friend Complex operator+(const Complex c1,const Complex c2);
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
Complex(double re = 0, double im = 0) {
this->re = re; int main() {
this->im = im; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
}
// error : more than one operator "+" matches
void print() { these operands
cout << re << " + j" << im << endl; c3 = c1 + c2;
}
c3.print();
// With constant arguments (pass by value)
Complex operator+(const Complex c2){ return 0;
cout << "Inside method : " ; }
return Complex( this->re + c2.re , this->im + c2.im );
}
};
Maulik N. Patoliya
Q-7
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-8
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Error
Method Reason for Error or
Case Arguments Type Occurred Output
Used Success
?
Member → non-const
M ⟶ +( *this , c2)
C4 Member + Friend val Yes “ambiguity”
F ⟶ +(const c1 , const c2)
friend → const val
Maulik N. Patoliya
Conclusion
Because, all arguments takes value not reference , and therefor both the function
work as same and compiler not able to decide that which function should be called.
Maulik N. Patoliya
Comparison
pass by reference pass by value
Error Error
Arguments Type Occurred Output Arguments Type Occurred Output
? ?
Both takes non-const & Yes “ambiguity” Both takes non-const val Yes “ambiguity”
Inside method:
Both takes const & No Both takes const val Yes “ambiguity”
3.3 + j3.3
Maulik N. Patoliya
Q-9
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-10
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-11
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-12
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-13
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Q-14
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
#include <iostream>
#include <cmath>
};
Maulik N. Patoliya
Conclusion
If arguments of member function is pass by reference and friend function
are pass by value , then doesn’t matter that arguments are constant or not ,
and generate ambiguity error.
If member argument is pass by value and friend arguments are pass reference
( const and non-const ) generate ambiguity error. ( Q-9 to Q-14 ; Except Q-12 )
Unique Case :
Member function takes ( non-const ) pass by value argument and friend function
takes constant reference , at that time code will compile fine and give output
with calling member function. ( Q - 12 )
Maulik N. Patoliya
Error
Method Reason for Error or
Case Arguments Type Occurred Output
Used Success
?
Maulik N. Patoliya
Error
Method Reason for Error or
Case Arguments Type Occurred Output
Used Success
?
Member ⟶ non-const
M ⟶ +( *this, c2) Inside method:
C4 Member + Friend val No
F ⟶ +(const& c1 , const& c2) 3.3 + j3.3
friend ⟶ const &
Member ⟶ non-const
M ⟶ +( *this , c2)
C5 Member + Friend val Yes “ambiguity”
F ⟶ +( & c1 , & c2 )
friend ⟶ non-const &
Maulik N. Patoliya
Final Conclusion :
The best approach is to define either a member or a friend operator+, not both. Use const
references in parameter(s) to maximize compatibility and avoid ambiguity.
If you want to define both , use const references in both member and friend functions to
avoid ambiguity and ensure correct function selection.
// Member function (const reference)
Complex operator+(const Complex& c2);
This ensures that the operator can be used correctly without ambiguity.
Maulik N. Patoliya