0% found this document useful (0 votes)
47 views25 pages

Operator Overloading Friends

Operator overloading allows operators like + and ++ to be used with user-defined types like classes. There are two main ways to overload operators: as non-member functions or as member functions. Non-member functions take the class as arguments while member functions take the object as the implicit first argument. Friend functions and classes can also access private members of other classes.

Uploaded by

Pranshu Jaiswal
Copyright
© Attribution Non-Commercial (BY-NC)
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)
47 views25 pages

Operator Overloading Friends

Operator overloading allows operators like + and ++ to be used with user-defined types like classes. There are two main ways to overload operators: as non-member functions or as member functions. Non-member functions take the class as arguments while member functions take the object as the implicit first argument. Friend functions and classes can also access private members of other classes.

Uploaded by

Pranshu Jaiswal
Copyright
© Attribution Non-Commercial (BY-NC)
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/ 25

Operator Overloading

Operator Overloading Friends

Junaed Sattar October 15, 2008 Lecture 7

Today

Overloading operators Friend functions and classes

Overloading Operators

Similar to function overloading Operators get additional power


formally they have definitions with respect to one or more classes i.e. they apply to classes

Example scenario
classComplex{ doublereal,imaginary; public: Complex():real(0.0),imaginary(0.0){ } Complex(doubler,doubleim):real(r), imaginary(im){ } ... }; intmain(){ Complexcm1,cm2(10,15); Complexcm3=cm1+cm2; }

But...

Will cause compiler error:


opov.cc: In function int main(): opov.cc:30: error: no match for operator+ in cm1 + cm2

Because the operator '+' has no meaning w.r.t. the Complex class! Two forms of the same solution:

overload '+' as a non-member function overload '+' as a member function

Form #1

Overload as a non-member function


const Complex operator+( const Complex &c1, const Complex &c2 ); number of operands equals the type of operator

one for unary, two for binary and so on

at least one operand must be a class type can be pass-by-value or -reference, with or without const

efficiency concerns

Form #1: Definition

Since not a member function, we need accessor functions

functions that are declared public and provide access to private members

double Complex::GetReal() const{ return real;} double Complex::GetImaginary() const { return imaginary; } const Complex operator+( const Complex &c1, const Complex &c2 ) { double r = c1.GetReal() + c2.GetReal(); double im = c1.GetImaginary() + c2.GetImaginary(); return Complex( r, im ); }

Special case: Unary operators

e.g. increment, decrement operators

const Complex operator++( const Complex &c);

But increment/decrement has prefix and suffix forms!

this applies only to the prefix form, i.e. Complex c2 = ++c1;

Form #2

Overload as a member function


const Complex operator+( const Complex &c2 ); number of operands equals one minus the type of operator

none for unary, one for binary and so on hence we omit it as an argument

the first operand is the calling object itself

Form #2 Definition

Since a member function, we have direct access to class member variables


const Complex Complex::operator+( const Complex &c2 ){ double r = this->GetReal() + c2.GetReal(); double im = this->GetImaginary() + c2.GetImaginary(); return Complex( r, im ); }

Both forms of unary increment/decrement can be defined:


const Complex operator++(); // prefix form const Complex operator++( int dummy ); // suffix form

The definition?
constComplexComplex::operator++ (intdummy){ ++this>real; ++this>imaginary; return*this; }

Why return a constant?

return statements create temporay objects

similar to passing by value

these temporary objects are assigned to the l-value

as opposed to r-values

this is valid:
Complex c3 = (c1+c2)++; // convince yourself

Different Classes?

adding a double to a Complex, or a Complex to a double?

does the order matter?


Complex c1; int i = 10; c1 = c1 + i; // will not work unless overloaded c1 = i + c1; // also has to be overloaded

Yes it does

More Overloading

remember, overloading as a member: the argument on the left is the calling class
constComplexComplex::operator+(inti);

to put the class as 2nd argument: use non-member operator functions

Friends of a class

not members, but can access private/protected elements


friend functions friend classes


class Complex { ... friend void Display( const Complex &c); ... }

commonly used for operator overloading

Define it

remember, real and imaginary are private


i.e. not directly accessible to non members functions but not so for friends

void Display( const Complex &c ) { cout << c.real << + << c.imaginary << i\n; ... }

OpOv with friends


class Complex { ... friend const Complex operator+( int i, Complex c ); ... } const Complex operator+( int i, Complex c ){ int added_r = i + c.real; int added_i = i + c.imaginary; return Complex( added_r, added_i ); ... }

Friend Classes

A friend class can access private or protected members of the class it is friends with Similar to friend functions (functionclass), but more elaborate (class-class) Declaration is different

Example
class Node{ int data; int key; friend class BinaryTree; // class BinaryTree can now access data directly }; class BinaryTree{ Node *root; int find(int key){ if(root->key == key){ // no need to go through an accessor function return root->data; } // perform rest of find }

Almost correct

But class Node does not know anything about class BinaryTree at the point where it is declared use forward declaration before declaring class Node
class BinaryTree; class Node{ ... }

Overloading >> and <<

Very useful, as an input/output tool

Helps implement serialization To be able to write statements like Complex c; cin >> c; cout << c <<endl; Argument on the left is not a user-defined object

Goal?

Problem?

Then, how?

Use the friend method for overloading Canonical forms:


ostream& operator << (ostream& os, const Complex& s); istream& operator >> (istream& is, Complex& s);

For the Complex class


istream& operator >> (istream& is, Complex& s) { is >> s.real >> s.imaginary; return is; }
//usage: Complex c; cin >> c; // enter the real part followed by the imaginary part, separated by a space 12 45 // that means 12+45i

The this pointer

keyword this identifies a special type of pointer Suppose:


object named x of class A class A has a member function f()

When calling the function x.f(), the keyword this in the body of f() stores the address of x

Example
struct X { private: int a; public: void Set_a(int a) { // The 'this' pointer is used to retrieve 'xobj.a' // hidden by the automatic variable 'a' this->a = a; } };

You might also like