Document Sample

```					Operator Overloading
Friends

Junaed Sattar
October 15, 2008

Lecture 7
Today


Friend functions and classes


−   formally they have definitions with respect to
one or more classes
−   i.e. they apply to classes
Example scenario
class Complex {
double real, imaginary;

public:
Complex(): real(0.0), imaginary(0.0){
}
Complex( double r, double im ) : real(r),
imaginary(im){
}
...
};
int main(){
Complex cm1, cm2(10, 15);
Complex cm3 = 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

−   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

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

−   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
−   the first operand is the calling object itself

hence we omit it as an argument
Form #2 Definition

Since a member function, we have direct
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?
const Complex Complex::operator++
(int dummy) {
++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?

Yes it does
−   Complex c1;
int i = 10;

c1 = c1 + i; // will not work unless overloaded
c1 = i + c1; // also has to be overloaded

argument on the left is the calling class

const Complex Complex::operator+( int i );

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);
...
}
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;

...
}
Friend Classes

A friend class can access private or
protected members of the class it is
friends with

Similar to friend functions (function-
class), 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{
...

}

Very useful, as an input/output tool
−   Helps implement serialization

Goal?
−   To be able to write statements like
Complex c;
cin >> c;
cout << c <<endl;

Problem?
−   Argument on the left is not a user-defined
object
Then, how?


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
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;
}
};

```
DOCUMENT INFO
Shared By:
Categories:
Stats:
 views: 121 posted: 3/30/2010 language: English pages: 25
How are you planning on using Docstoc?