Friends and more!


The following topics are covered in this section:


Friend Function

The private member data of a class can be accessed only by the class' member functions. Well, there is one exception. A friend function will be friendly with a class even though it is not a member of that class. By the term friendly we mean that the friend function can access the private members of the class. Check out the example below:

#include <iostream.h>
class car
{
private:
    int speed;
    char color[20];

public:
void input( )
{
cout<<"\nEnter the color : ";
cin>>color;
cout<<"\nEnter the speed : ";
cin>>speed;
}

friend void display(car); //Friend of the class 'car'
};

void display(car x)
{
cout<<"\nThe color of the car is : "<<x.color;
cout<<"\nThe speed of the car is : "<<x.speed;
}

int main( )
{
car mine;
mine.input( ); //accessing a member function
display(mine); //passing the object ‘mine’ to the friend function
return 0;
}

The output is:

Enter the color : red
Enter the speed : 345
The color of the car is : red
The speed of the car is : 345

First of all we've created a class named car. It has two private data: color and ‘speed’ and one public function ‘input’. It also has a friend function called display ( ).

Next comes the definition of display ( ):

int display (car x)

The parameter specifies an object of type ‘car’. The function has been defined to output:

x.color;
x.speed;

The idea is that you will pass an object of type ‘car’ to this function and the function will display the corresponding color and speed values for that particular object.

In the main ( ) part, an object called ‘mine’ has been created whose private data are set by the user through the input ( ) function. Next the friend function has been called:

display(mine);

Remember: Friend functions are not members of any class but they can access private data of the class to which they are a friend.

Beware: Since they are not members of any class, you should not call them using the dot operator.

You might be wondering what's the big point of friend functions. In the above example, we could have made ‘display’ as a member function of the class instead of declaring it as a friend function. What's the use? A friend function can be friendly to 2 or more classes. The friend function does not belong to any class, so it can be used to access private data of two or more classes. No other function can do that!

#include <iostream.h>
class virus; // forward declaration of ‘virus’ class

class bacteria
{
private:
    int life;

public:
bacteria( )
{
    life=1;
}

friend void check(bacteria, virus);
};

class virus
{
private:
    int life;

public:
virus( ):life(0)
{}

friend void check(bacteria, virus);
};

void check (bacteria b,virus v)
{


if (b.life= =1 || v.life= =1)
{
cout<<"\nSomething is alive";
}
if (b.life = = 1)
{
cout<<"\nA bacteria is alive.";
}
if (v.life = = 1)
{
cout<<"\nA virus is alive.";
}
}

int main( )
{
bacteria fever;
virus cholera;
check(fever, cholera);
return 0;
}

In the second line of the program we have the statement:

class virus;

This is a forward declaration of the class ‘virus’. This is done because when the compiler reads through the lines in the ‘bacteria’ class, it encounters the word ‘virus’ in the friend function declaration. Until this point it doesn't know what ‘virus’ is because we will be defining the ‘virus’ class later on. So we tell the compiler in advance that ‘virus’ is a class by declaring it in the starting itself. If you don't declare it, you will get errors. Just try it out.

One more note: You should declare the friend function in both the classes where you want it to be a friend.

In this program we want to check whether any organism is alive at present by testing the value of ‘life’. Of course you can write individual member functions in each class but the use of a friend function makes it simpler and easier to understand the logic.


Friend Classes

Just like functions are made friends of classes, we can also make one class to be a friend of another class. In this way, the friend class will have access to all the private members of the other class.

#include <iostream.h>
class add
{
private:
    int x,y;

public:
add( )
{
x=y=4;|
}

friend class support; //support is now a friend of add
};

class support
{
public:
void sum(add ob) //it can access private members of class 'add’
{
cout<<"The sum of the 2 members is : "<<(ob.x+ob.y);
}

};

int main( )
{
add ad;
support sup;
sup.sum(ad);
return 0;
}

The output will be:

The sum of the 2 members is : 8

In this program, the class ‘support’ is a friend of the class ‘add’. Thus the class ‘support’ can access all the private members of the class ‘add’ (i.e. ‘x’ and ‘y’). Friend classes are rarely used.


Static Class Members

A class is just an empty area. No area is allocated when you create a class. So, only when you create an object of that class will the compiler allocate space to the object. Again, this means that:

private:
int x;

does not allocate space for an integer x. When you create objects belonging to this class, required space is allocated for holding the integer. Each new object that you create belonging to this class will have its own version of the integer ‘x’. The keyword ‘static’ helps you to create a single copy for all objects belonging to the same class.

#include <iostream.h>
class bacteria
{
private:
static int count;

public:
void modify( )
{
count=count+1;
cout<<endl<<"The new count is : "<<count;
}

};

int bacteria::count=5; // memory allocated for ‘count’ over here

int main( )
{
bacteria b;
bacteria plague;
b.modify( );
plague.modify( );
plague.modify( );
return 0;
}

The output is:

The new count is : 6
The new count is : 7
The new count is : 8

The integer ‘count’ is declared to be static. But again outside the class we say:

int bacteria::count=5;

This is done so that the compiler will allocate space for the integer ‘count’. If ‘count’ were not static, when would the compiler allocate space to it? It would allocate space when an object is created. But in the case of static variable members in a class, we will create it only once and so we have to ensure that the compiler creates that one instance of the variable. In this case we’ve initialized it to a starting value of 5. If you simply type:

int bacteria::count;

‘count’ would be automatically initialized to 0. Since ‘count’ is static, each time you change the value of ‘count’, all the objects belonging to that class will make use of the new value.

So far we’ve seen static member data but you can also make functions static in a class. Just precede the function by the keyword static. Static functions will be useful to operate on static member data.


Constant Object

Classes are user-defined types and objects can also be made constant using the ‘const’ keyword. When an object is made constant there are some peculiar properties that you should take note of. A constant object is created to avoid making changes to any of the values of the member data (that is the purpose of constant in general and so is the case with constant objects).

1.) Constant objects cannot access member functions that are not constant.

#include <iostream.h>
class bacteria
{
private:
int life,count;

public:

bacteria( )
{
life=1;
}

void display( )
{
cout<<endl<<"The life of bacteria is : "<<life;
}

};

int main( )
{
const bacteria fever;
fever.display( ); //COMPILER ERROR
return 0;
}

The error results because display ( ) is not a constant member function. Ideally, an object that is constant should not be able to modify any of its member data values. You might ask, "The display function doesn’t modify any values; so why can’t we call it?" The compiler when reading through the code will not believe that a member function doesn’t change any values (even if it really doesn’t). There is a good chance that the member function might be defined in some other file and the compiler might never know about the definition (you’ll see this in multiple file programming). Hence, irrespective of whether the function changes a value or not, a constant object cannot access the non-constant functions.

2.) So, the question arises, what are constant functions? Constant functions can be called by constant objects. The compiler doesn’t know when a function modifies data values and when a function doesn’t. When you make a function constant, the compiler believes that the function will not change any of the member data values. To create a constant function you have to simply add the keyword ‘const’ at the end of the function.

class bacteria
{
private:
int life,count;

public:
bacteria( )
{
life=0;
}

void display( ) const
{
cout<<endl<<"The life of bacteria is : "<<life;
}

};

int main( )
{
const bacteria fever;
fever.display( );
return 0;
}

The output is:

The life of bacteria is : 0

The program will now run because a constant object is calling a constant member function.

Beware: Don’t make a function constant and then write a code within the body to modify some member data value. The compiler will produce an error. Try it and see.

3.) Can a constant member function never modify any member value? Again there is an exception to this. If a member data is declared as ‘mutable’, then the constant member function can modify this member data. You might wonder what purpose this would solve? There might be a case where you want to keep count of something for all objects (irrespective of whether they are constant objects or not). In this case, a constant object should also be able to access such member data.

Let’s take the same case of the bacteria class. We shall make the member data ‘life’ mutable.

class bacteria
{
private:
mutable int life;

public:
bacteria( )
{
life=0;
}

void display( ) const
{
life=life+1;
cout<<endl<<"The life of bacteria is : "<<life;
}

};

int main( )
{
const bacteria fever;
fever.display( );
return 0;
}

The output is:

The life of bacteria is : 1

Since ‘life’ is mutable, the constant function can modify this variable.


Go back to the Contents Page


Copyright © 2004 Sethu Subramanian All rights reserved. Sign My Guestbook