Friend Function : As we know, private class members can not be accessed from outside the class. By using private class members, we can reduce the possibility of a program misusing a member's value, since the program must access the class members using an interface function. Sometime, we would like two classes to share a particular function. In such situation, C++ allows the common function to be made friendly with both classes, thereby allowing the function to have access to the private data of these classes. Such a function need not be a member of any of these classes.
To make an outside function 'friendly' to a class, we have to simply declare this function as a friend of the class. The function declaration should be preceded by the keyword friend. While the function definition does not use either the keyword friend or scope resolution operator (::). The function that are declared with the keyword friend are known as friend functions. A function can be declared friend in any number of classes.
A friend function possesses certain characteristics :
- It can be declared either in the public or private part of a class without affecting its meaning.
- Usually, it has objects as arguments.
- Its scope is not limited to the class in which it has been declared as friend. It can not be called using the object of that class. It can be invoked like a normal function without the help of any object.
- Unlike the normal member functions, it can not access the member names directly. It has to use an object name and dot membership operator with each member name.
Example,
#include <iostream.h>
class sample
{
int a;
int b;
public :
void setvalue( int al, int bl)
{
a = a1;
b = b1;
}
friend float mean (sample s); //friend declared
};
float mean(sample s) //function definition
{
return float(s.a + s.b) / 2; //accessing private members
}
void main ()
{
sample x; //create an object x
x.setvalue(25,40);
cout << "Mean Value : " << mean(x) << endl;
}
All the member functions of one class can be declared as friend functions of another class. In such a case,the class is called a friend class. This can be specified as follows:
class X;
class Z
{
......
friend class X; //all member functions of X are friends to Z
};
Constructors : These are special member functions that are used to initialize the objects, as soon as they are created. Thst is, you can create an object and simultaneously pass the value to the parameters of the object. The constructors should have exactly the same name as that of class of which they are members. The constructor function does not have a return value. They should be declared in public section. To understand how constructors are used, let's try the example of displaying the area of square by using constructors :
Example,
class Square
{
public :
int dim;
Square(int d); //Declaring a Constructor Function
{
dim = d;
}
void DisplayArea()
{
cout << "The area of the square : "<<dim*dim;
}
void main ()
{
Square S1(10), S2(15); //the constructor function will be called automatically
cout << "The dimension of the square is : " << s1.dim;
S1.DisplayArea();
cout << "The dimension of the square is :" << s1.dim;
S2.DisplayArea();
}
The output of the program will be :
The dimension of the square is 10
The area of the square : 100
The dimension of the square is 15
The area of the square : 225
Copy Constructor : It is used to declare an object and the values of these objects are initialized from other object. Note that a copy constructor takes a reference to an object of the same class. We can not pass the argument by value to a copy constructor.
Example,
#include <iostream.h>
class Square
{
int dim;
public :
Square();
{ }
Square (int I)
{
dim = I;
}
Square (Square & j) //passing the argument through reference not by value
{ dim = x.dim; }
void Display()
{
cout << dim;
cout << "\n The area is : "<<dim*dim;
}
};
main ()
{
Square Square1(10);
Square Square1(Square2); //declaring a copy constructor
Square Square3 = Square1; //declaring a copy constructor
cout << "\n length of square1 " ;
Square1.Display();
cout << "\n length of square2 " ;
Square2.Display();
cout << "\n length of square3 " ;
Square3.Display();
}
The output is :
Length of square1 : 10
The area is : 100
length of square2 : 10
The area is : 100
Length of Square3 : 10
The area is : 100
Dynamic Constructors : They are used to allocate memory to objects at the time of their creation. Normally we can allocate fixed amount of memoryby using array but in many situations, we are not sure how much memory we need until runtime. For example, space required to store the length of string entered by user.
In such case, we use 'new' operator. This operator obtains memory space from operating system and returns a pointer to its starting point. We can use 'new' operators in constructors to dynamically assign storage space when objects are created.
Keywords: class, constructor, copy constructor, dynamic, friend function


Comments
Basic Concepts
These are some of the basic concepts of object-oriented languages.- Classes and objects. A class is similar to a C structure, except that the definition of the data structure, and all of the functions that operate on the data structure are grouped together in one place. An object is an instance of a class (an instance of the data structure); objects share the same functions with other objects of the same class, but each object (each instance) has its own copy of the data structure. A class thus defines two aspects of the objects: the data they contain, and the behavior they have.
- Member functions. These are functions which are considered part of the object and are declared in the class definition. They are often referred to as methods of the class. In addition to member functions, a class's behavior is also defined by:
- What to do when you create a new object (the constructor for that object) - in other words, initialize the object's data.
- What to do when you delete an object (the destructor for that object).
- Private vs. public members. A public member of a class is one that can be read or written by anybody, in the case of a data member, or called by anybody, in the case of a member function. A private member can only be read, written, or called by a member function of that class.
Classes are used for two main reasons: (1) it makes it much easier to organize your programs if you can group together data with the functions that manipulate that data, and (2) the use of private members makes it possible to do information hiding, so that you can be more confident about the way information flows in your programs.Classes
C++ classes are similar to C structures in many ways. In fact, a C++ struct is really a class that has only public data members. In the following explanation of how classes work, we will use a stack class as an example.class Stack {
This class has two data members, top and stack, and one member function, Push. The notation class::function denotes the function member of the class class. (In the style we use, most function names are capitalized.) The function is defined beneath it.public:
void Push(int value); // Push an integer, checking for overflow.
int top; // Index of the top of the stack.
int stack[10]; // The elements of the stack.
};
void
Stack::Push(int value) {
ASSERT(top < 10); // stack should never overflow
stack[top++] = value;
}
As an aside, note that we use a call to ASSERT to check that the stack hasn't overflowed; ASSERT drops into the debugger if the condition is false. It is an extremely good idea for you to use ASSERT statements liberally throughout your code to document assumptions made by your implementation. Better to catch errors automatically via ASSERTs than to let them go by and have your program overwrite random locations.
In actual usage, the definition of class Stack would typically go in the file stack.h and the definitions of the member functions, like Stack::Push, would go in the file stack.cc.
If we have a pointer to a Stack object called s, we can access the top element as s->top, just as in C. However, in C++ we can also call the member function using the following syntax:
Of course, as in C, s must point to a valid Stack object.Inside a member function, one may refer to the members of the class by their names alone. In other words, the class definition creates a scope that includes the member (function and data) definitions.
Note that if you are inside a member function, you can get a pointer to the object you were called on by using the variable this. If you want to call another member function on the same object, you do not need to use the this pointer, however. Let's extend the Stack example to illustrate this by adding a Full() function.
class Stack {
Now we can rewrite Push this way: We could have also written the ASSERT: but in a member function, the this-> is implicit.public:
void Push(int value); // Push an integer, checking for overflow.
bool Full(); // Returns TRUE if the stack is full, FALSE otherwise.
int top; // Index of the lowest unused position.
int stack[10]; // A pointer to an array that holds the contents.
};
bool
Stack::Full() {
return (top == 10);
}
The purpose of member functions is to encapsulate the functionality of a type of object along with the data that the object contains. A member function does not take up space in an object of the class.
In our stack example, note that once we have the Full() function, we really don't need to look at the top or stack members outside of the class - in fact, we'd rather that users of the Stack abstraction not know about its internal implementation, in case we change it. Thus we can rewrite the class as follows:
class Stack {
Before, given a pointer to a Stack object, say s, any part of the program could access s->top, in potentially bad ways. Now, since the top member is private, only a member function, such as Full(), can access it. If any other part of the program attempts to use s->top the compiler will report an error.public:
void Push(int value); // Push an integer, checking for overflow.
bool Full(); // Returns TRUE if the stack is full, FALSE otherwise.
private:
int top; // Index of the top of the stack.
int stack[10]; // The elements of the stack.
};
You can have alternating public: and private: sections in a class. Before you specify either of these, class members are private, thus the above example could have been written:
class Stack {
Which form you prefer is a matter of style, but it's usually best to be explicit, so that it is obvious what is intended. In Nachos, we make everything explicit.int top; // Index of the top of the stack.
int stack[10]; // The elements of the stack.
public:
void Push(int value); // Push an integer, checking for overflow.
bool Full(); // Returns TRUE if the stack is full, FALSE otherwise.
};
What is not a matter of style: all data members of a class should be private. All operations on data should be via that class' member functions. Keeping data private adds to the modularity of the system, since you can redefine how the data members are stored without changing how you access them.
The way this is done in C++ is as follows:
The new function takes the place of malloc(). To specify how the object should be initialized, one declares a constructor function as a member of the class, with the name of the function being the same as the class name:class Stack {
There are a few things going on here, so we will describe them one at a time.public:
Stack(int sz); // Constructor: initialize variables, allocate space.
void Push(int value); // Push an integer, checking for overflow.
bool Full(); // Returns TRUE if the stack is full, FALSE otherwise.
private:
int size; // The maximum capacity of the stack.
int top; // Index of the lowest unused position.
int* stack; // A pointer to an array that holds the contents.
};
Stack::Stack(int sz) {
size = sz;
top = 0;
stack = new int[size]; // Let's get an array of integers.
}
The new operator automatically creates (i.e. allocates) the object and then calls the constructor function for the new object. This same sequence happens even if, for instance, you declare an object as an automatic variable inside a function or block - the compiler allocates space for the object on the stack, and calls the constructor function on it.
In this example, we create two stacks of different sizes, one by declaring it as an automatic variable, and one by using new.
Note there are two ways of providing arguments to constructors: with new, you put the argument list after the class name, and with automatic or global variables, you put them after the variable name.It is crucial that you always define a constructor for every class you define, and that the constructor initialize every data member of the class. If you don't define your own constructor, the compiler will automatically define one for you, and believe me, it won't do what you want ("the unhelpful compiler"). The data members will be initialized to random, unrepeatable values, and while your program may work anyway, it might not the next time you recompile (or vice versa!).
As with normal C variables, variables declared inside a function are deallocated automatically when the function returns; for example, the s1 object is deallocated when test returns. Data allocated with new (such as s2) is stored on the heap, however, and remains after the function returns; heap data must be explicitly disposed of using delete, described below.
The new operator can also be used to allocate arrays, illustrated above in allocating an array of ints, of dimension size:
Note that you can use new and delete (described below) with built-in types like int and char as well as with class objects like Stack.class Stack {
The destructor has the job of deallocating the data the constructor allocated. Many classes won't need destructors, and some will use them to close files and otherwise clean up after themselves.public:
Stack(int sz); // Constructor: initialize variables, allocate space.
~Stack(); // Destructor: deallocate space allocated above.
void Push(int value); // Push an integer, checking for overflow.
bool Full(); // Returns TRUE if the stack is full, FALSE otherwise.
private:
int size; // The maximum capacity of the stack.
int top; // Index of the lowest unused position.
int* stack; // A pointer to an array that holds the contents.
};
Stack::~Stack() {
delete [] stack; // delete an array of integers
}
The destructor for an object is called when the object is deallocated. If the object was created with new, then you must call delete on the object, or else the object will continue to occupy space until the program is over - this is called "a memory leak." Memory leaks are bad things - although virtual memory is supposed to be unlimited, you can in fact run out of it - and so you should be careful to always delete what you allocate. Of course, it is even worse to call delete too early - delete calls the destructor and puts the space back on the heap for later re-use. If you are still using the object, you will get random and non-repeatable results that will be very difficult to debug. In my experience, using data that has already been deleted is major source of hard-to-locate bugs in student (and professional) programs, so hey, be careful out there!
If the object is an automatic, allocated on the execution stack of a function, the destructor will be called and the space deallocated when the function returns; in the test() example above, s1 will be deallocated when test() returns, without you having to do anything.
In Nachos, we always explicitly allocate and deallocate objects with new and delete, to make it clear when the constructor and destructor is being called. For example, if an object contains another object as a member variable, we use new to explicitly allocated and initialize the member variable, instead of implicitly allocating it as part of the containing object. C++ has strange, non-intuitive rules for the order in which the constructors and destructors are called when you implicitly allocate and deallocate objects. In practice, although simpler, explicit allocation is slightly slower and it makes it more likely that you will forget to deallocate an object (a bad thing!), and so some would disagree with this approach.
When you deallocate an array, you have to tell the compiler that you are deallocating an array, as opposed to a single element in the array. Hence to delete the array of integers in Stack::~Stack:
Other Basic C++ Features
Here are a few other C++ features that are useful to know.As an example, we could make the Full routine an inline.
class Stack {
There are two motivations for inlines: convenience and performance. If overused, inlines can make your code more confusing, because the implementation for an object is no longer in one place, but spread between the .h and .c files. Inlines can sometimes speed up your code (by avoiding the overhead of a procedure call), but that shouldn't be your principal concern as a student (rather, at least to begin with, you should be most concerned with writing code that is simple and bug free). Not to mention that inlining sometimes slows down a program, since the object code for the function is duplicated wherever the function is called, potentially hurting cache performance....
bool Full() { return (top == size); };
...
};
For example, you can declare that a member function only reads the member data, and never modifies the object:
class Stack {
As in C, you can use const to declare that a variable is never modified: This is much better than using #define for constants, since the above is type-checked....
bool Full() const; // Full() never modifies member data
...
};