0% found this document useful (0 votes)
3 views

Operator_Overloading_( Member + Friend Function Behavior)

The document contains code examples and explanations related to operator overloading in C++ using a Complex class. It discusses the behavior of friend functions versus member functions when resolving operator overloads, particularly focusing on const and non-const references. The document concludes with conditions under which certain overloads succeed or fail, emphasizing the importance of argument types in function resolution.

Uploaded by

riturupapara11
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Operator_Overloading_( Member + Friend Function Behavior)

The document contains code examples and explanations related to operator overloading in C++ using a Complex class. It discusses the behavior of friend functions versus member functions when resolving operator overloads, particularly focusing on const and non-const references. The document concludes with conditions under which certain overloads succeed or fail, emphasizing the importance of argument types in function resolution.

Uploaded by

riturupapara11
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 39

NAME : PATOLIYA MAULIKKUMAR NARENDRABHAI

BRANCH : CE ( 24CEUOG121 )
BATCH : A2
ROLL NO, : 041
SUB : ADVANCED C++ PROGRAMMING CONCEPTS
FOCUS: OVERLOAD RESOLUTION | COMPILER BEHAVIOR
Q-1

#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
double re; Complex operator+( Complex &c1, Complex &c2){
double im; cout << "Inside friend : " ;
return Complex(c1.re+c2.re , c1.im+c2.im);
public: }

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);
}

// Without constant arguments(pass by reference)


friend Complex operator+( Complex &c1, Complex &c2);

};

Maulik N. Patoliya
Q-2

#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by reference)
class Complex {
double re; Complex operator+(const Complex &c1,const Complex &c2){
double im; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im );
public: }

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>

using namespace std;


// With constant arguments (pass by reference)
class Complex {
double re; Complex operator+(const Complex &c1,const Complex &c2){
double im; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im );
public: }

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 );
}

// With constant arguments(pass by reference)


friend Complex operator+(const Complex &c1,const Complex &c2);

};

Maulik N. Patoliya
Q-3

#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
double re; Complex operator+( Complex &c1, Complex &c2){
double im; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im );
public: }

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>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
double re; Complex operator+( Complex &c1, Complex &c2){
double im; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im );
public: }

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 );
}

// Without constant arguments(pass by reference)


friend Complex operator+( Complex &c1, Complex &c2);

};

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.

Checking Member Function


The member function requires const Complex& as an argument.
Since c1 is calling it (c1.operator+(c2)), this is implicitly passed as Complex* const this.
This means this (which is Complex* const) cannot bind to the member function, since operator+
is not a const member function.

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>

using namespace std;


// With constant arguments (pass by reference)
class Complex {
double re; Complex operator+(const Complex &c1,const Complex &c2){
double im ; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im);
public: }

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>

using namespace std;


// With constant arguments (pass by reference)
class Complex {
double re; Complex operator+(const Complex &c1,const Complex &c2){
double im ; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im);
public: }

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 );
}

// With constant arguments(pass by reference)


friend Complex operator+(const Complex &c1,const Complex &c2);

};

Maulik N. Patoliya
Error
Method Reason for Error or
Case Arguments Type Occurred Output
Used Success
?

M ⟶ +( *this, & c2)


C1 Member + Friend Both takes non-const & Yes “ambiguity”
F ⟶ +(& c1 , & c2)

M ⟶ +( *this , const& c2) Inside method:


C2 Member + Friend Both takes const & No
F ⟶ +(const& c1 , const& c2) 3.3 + j3.3

Member → const & M ⟶ +( *this , const& c2) Inside friend:


C3 Member + Friend No
friend → non-const & F ⟶ +(& c1 , & c2) 3.3 + j3.3

Member → non-const & M ⟶ +( *this , & c2) Inside method:


C4 Member + Friend No
friend → const & F ⟶ +(const& c1 , const& c2) 3.3 + j3.3

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>

using namespace std;


// Without constant arguments (pass by value)
class Complex {
Complex operator+( Complex c1, Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void print() {
cout << re << " + j" << im << endl; return 0;
} }

// Without constant arguments (pass by value)


Complex operator+( Complex c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
} output ?
// Without constant arguments (pass by value)
friend Complex operator+( Complex c1, Complex c2);

};

Maulik N. Patoliya
#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by value)
class Complex {
Complex operator+( Complex c1, Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// Without constant arguments (pass by value) return 0;


Complex operator+( Complex c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// Without constant arguments (pass by value)


friend Complex operator+( Complex c1, Complex c2);

};

Maulik N. Patoliya
Q-6

#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by value)
class Complex {
double re; Complex operator+(const Complex c1,const Complex c2){
double im; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im );
public: }

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>

using namespace std;


// With constant arguments (pass by value)
class Complex {
double re; Complex operator+(const Complex c1,const Complex c2){
double im; cout << "Inside friend : " ;
return Complex( c1.re + c2.re , c1.im + c2.im );
public: }

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 );
}

// With constant arguments (pass by value)


friend Complex operator+(const Complex c1,const Complex c2);

};

Maulik N. Patoliya
Q-7

#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by value)
class Complex {
Complex operator+( Complex c1, Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void 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 ?
// Without constant arguments (pass by value)
friend Complex operator+( Complex c1, Complex c2);

};

Maulik N. Patoliya
#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by value)
class Complex {
Complex operator+( Complex c1, Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// With constant arguments (pass by value) return 0;


Complex operator+(const Complex c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// Without constant arguments (pass by value)


friend Complex operator+( Complex c1, Complex c2);

};

Maulik N. Patoliya
Q-8

#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by value)
class Complex {
Complex operator+(const Complex c1,const Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void print() {
cout << re << " + j" << im << endl; return 0;
} }

// Without constant arguments (pass by value)


Complex operator+( 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>

using namespace std;


// With constant arguments (pass by value)
class Complex {
Complex operator+(const Complex c1,const Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// Without constant arguments (pass by value) return 0;


Complex operator+( Complex c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// With constant arguments (pass by value)


friend Complex operator+(const Complex c1,const Complex c2);

};

Maulik N. Patoliya
Error
Method Reason for Error or
Case Arguments Type Occurred Output
Used Success
?

Both takes non-const M ⟶ +( *this, c2)


C1 Member + Friend Yes “ambiguity”
val F ⟶ +( c1 , c2)

M ⟶ +( *this , const c2)


C2 Member + Friend Both takes const val Yes “ambiguity”
F ⟶ +(const c1 , const c2)

Member → const val M ⟶ +( *this , const c2)


C3 Member + Friend Yes “ambiguity”
friend → non-const val F ⟶ +( c1 , c2)

Member → non-const
M ⟶ +( *this , c2)
C4 Member + Friend val Yes “ambiguity”
F ⟶ +(const c1 , const c2)
friend → const val

Maulik N. Patoliya
Conclusion

If all arguments (parameters) of member and friend function are passed by


value , then it gives ambiguous error.

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.

Doesn’t matter that arguments are constant or not.

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

Member → const & Inside friend: Member → const val


No Yes “ambiguity”
friend → non-const & 3.3 + j3.3 friend → non-const val

Member → non-const & Inside method: Member → non-const val


No Yes “ambiguity”
friend → const & 3.3 + j3.3 friend → const val

Maulik N. Patoliya
Q-9

#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by value)
class Complex {
Complex operator+( Complex c1, Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void 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 argumAents (pass by value)
friend Complex operator+( Complex c1, Complex c2);

};

Maulik N. Patoliya
#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by value)
class Complex {
Complex operator+( Complex c1, Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// With constant arguments (pass by reference) return 0;


Complex operator+(const Complex &c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// Without constant argumAents (pass by value)


friend Complex operator+( Complex c1, Complex c2);

};

Maulik N. Patoliya
Q-10

#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by value)
class Complex {
Complex operator+(const Complex c1,const Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} 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 value)
friend Complex operator+(const Complex c1,const Complex c2);

};

Maulik N. Patoliya
#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by value)
class Complex {
Complex operator+(const Complex c1,const Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// With constant arguments (pass by reference) return 0;


Complex operator+(const Complex &c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// With constant arguments (pass by value)


friend Complex operator+(const Complex c1,const Complex c2);

};

Maulik N. Patoliya
Q-11

#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by value)
class Complex {
Complex operator+(const Complex c1,const Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
}
c3 = c1 + c2;
void print() {
cout << re << " + j" << im << endl; c3.print();
}
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 value)
friend Complex operator+(const Complex c1,const Complex c2);

};

Maulik N. Patoliya
#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by value)
class Complex {
Complex operator+(const Complex c1,const Complex c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// Without constant arguments (pass by reference) return 0;


Complex operator+( Complex &c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// With constant arguments (pass by value)


friend Complex operator+(const Complex c1,const Complex c2);

};

Maulik N. Patoliya
Q-12

#include <iostream>
#include <cmath>

using namespace std;


// With constant arguments (pass by reference)
class Complex {
Complex operator+(const Complex &c1,const Complex &c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void print() {
cout << re << " + j" << im << endl; return 0;
} }

// Without constant arguments (pass by value)


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>

using namespace std;


// With constant arguments (pass by reference)
class Complex {
Complex operator+(const Complex &c1,const Complex &c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void print() {
cout << re << " + j" << im << endl; return 0;
} }

// Without constant arguments (pass by value)


Complex operator+( Complex c2){
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// With constant arguments (pass by reference)


friend Complex operator+(const Complex &c1,const Complex &c2);

};

Maulik N. Patoliya
Q-13

#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
Complex operator+( Complex &c1, Complex &c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void print() {
cout << re << " + j" << im << endl; return 0;
} }

// Without constant arguments (pass by value)


Complex operator+( 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>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
Complex operator+( Complex &c1, Complex &c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// Without constant arguments (pass by value) return 0;


Complex operator+( Complex c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// Without constant arguments (pass by reference)


friend Complex operator+( Complex &c1, Complex &c2);

};

Maulik N. Patoliya
Q-14

#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
Complex operator+( Complex &c1, Complex &c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} c3 = c1 + c2;
c3.print();
void 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 ?
// Without constant arguments (pass by reference)
friend Complex operator+( Complex &c1, Complex &c2);

};

Maulik N. Patoliya
#include <iostream>
#include <cmath>

using namespace std;


// Without constant arguments (pass by reference)
class Complex {
Complex operator+( Complex &c1, Complex &c2){
double re; cout << "Inside friend : " ;
double im; return Complex( c1.re + c2.re , c1.im + c2.im );
}
public:

Complex(double re = 0, double im = 0) { int main() {


this->re = re; Complex c1(1.1, 1.1) , c2(2.2, 2.2) , c3 ;
this->im = im;
} // error : more than one operator "+" matches
these operands
void print() { c3 = c1 + c2;
cout << re << " + j" << im << endl;
} c3.print();

// With constant arguments (pass by value) return 0;


Complex operator+(const Complex c2){ }
cout << "Inside method : " ;
return Complex( this->re + c2.re , this->im + c2.im );
}

// Without constant arguments (pass by reference)


friend Complex operator+( Complex &c1, Complex &c2);

};

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
?

Member ⟶ const & M ⟶ +( *this, const& c2)


C1 Member + Friend Yes “ambiguity”
friend ⟶ non-const val F ⟶ +( c1 , c2)

Member ⟶ const & M ⟶ +( *this , const& c2)


C2 Member + Friend Yes “ambiguity”
friend ⟶ const val F ⟶ +(const c1 , const c2)

Member → non-const & M ⟶ +( *this , & c2)


C3 Member + Friend Yes “ambiguity”
friend → const val F ⟶ +(const c1 ,const c2)

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 &

Member → const val M ⟶ +( *this , const c2)


C6 Member + Friend Yes “ambiguity”
friend → non-const & F ⟶ +(& c1 ,& c2)

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);

// Friend function (const reference)


friend Complex operator+(const Complex& c1, const Complex& c2);

This ensures that the operator can be used correctly without ambiguity.

Maulik N. Patoliya

You might also like