OOP Features and C++ Dereferencing Explained
OOP Features and C++ Dereferencing Explained
Ans : OOPs is an Object Oriented Programming language, which is the extension of Procedure
Oriented Programming language. OOPS reduce the code of the Program because of the
extensive feature of Polymorphism. OOPS have many properties such as Data-Hiding,
Inheritance, Data Abstraction, Data Encapsulation and many more. Everything in the world is an
object. The type of the object may vary. In OOPS, we get the power to create objects of our
own, as & when required.
The Objects Oriented programming language supports all the features of normal programming
languages. In addition it supports some important concepts and terminology which has made it
popular among programming methodology.
Inheritance
Polymorphism
Data Hiding
Encapsulation
Abstraction
Overloading
Reusability
Objects
Classes
Objects:
In other words object is an instance of a class. Dividing with into objects solves a problem,which
results in a close resemblance between the objects in programming sense and objects in the
programming sense and objects in the real world.
Classes:
These contain data and functions bundled together under a unit. In other words class is a
collection of similar objects. When we define a class it just creates template or Skelton. So no
memory is created when class is created. Memory is occupied only by object.
Example: Class classname
{
Data
Functions
};
main ( )
{
classname objectname1,objectname2,..;
}
Data Hiding:
This concept is the main heart of an Object oriented programming. The data is hidden inside
the class by declaring it as private inside the class. When data or functions are defined as
private it can be accessed only by the class in which it is defined. When data or functions are
defined as public then it can be accessed anywhere outside the class. Object Oriented
programming gives importance to protecting data which in any system. This is done by
declaring data as private and making it accessible only to the class in which it is defined. This
concept is called data hiding. But one can keep member functions as public.
So above class structure becomes
The technical term for combining data and functions together as a bundle is encapsulation.
Encapsulation is the phenomenon of binding the data members and the functions, which
operate on that data in a unit thereby `encapsulating' them. Abstraction is the phenomenon by
which the access to a data is restricted making it saving from unintentional manipulation.
Inheritance:
Inheritance as the name suggests is the concept of inheriting or deriving properties of an exiting
class to get new class or classes. In other words we may have common features or
characteristics that may be needed by number of classes. So those features can be placed in a
common tree class called base class and the other classes which have these charaterisics can
take the tree class and define only the new things that they have on their own in their classes.
These classes are called derived class. The main advantage of using this concept of inheritance
in Object oriented programming is it helps in reducing the code size since the common
characteristic is placed separately called as base class and it is just referred in the derived class.
This provide the users the important usage of terminology called as reusability
Reusability:
This usage is achieved by the above explained terminology called as inheritance. Reusability is
nothing but re- usage of structure without changing the existing one but adding new features or
characteristics to it. It is very much needed for any programmers in different situations.
Reusability gives the following advantages to users.
It helps in reducing the code size since classes can be just derived from existing one and one
need to add only the new features and it helps users to save their time.
For instance if there is a class defined to draw different graphical figures say there is a user who
want to draw graphical figure and also add the features of adding color to the graphical figure.
In this scenario instead of defining a class to draw a graphical figure and coloring it what the
user can do is make use of the existing class for drawing graphical figure by deriving the class
and add new feature to the derived class namely add the feature of adding colors to the
graphical figure.
Poly refers many. So Polymorphism as the name suggests is a certain item appearing in
different forms or ways. That is making a function or operator to act in different forms
depending on the place they are present is called Polymorphism. Overloading is a kind of
polymorphism. In other words say for instance we know that +, - operate on integer data type
and is used to perform arithmetic additions and subtractions. But operator overloading is one in
which we define new operations to these operators and make them operate on different data
types in other words overloading the existing functionality with new one. This is a very
important feature of object oriented programming methodology which extended the handling
of data type and operations.
Thus the above given important features of object oriented programming among the numerous
features it have gives the following advantages to the programming world. The advantages are
namely
Ans : It is possible to access the value of variables pointed by the pointer variables using
pointer. This is performed by using the Dereference operator in C++ which has the notation *.
In this example, pointer variable denotes the variable defined as pointer. The * placed before
the pointer_variable denotes the value pointed by the pointer_variable.
For example:
myvariable = 500;
alpha = myvariable;
x = & myvariable;
y=*x;
In the above example, the myvariable is a integer variable having the value of 500 stored in
memory address location 3021.
The variable myvariable is assigned to the variable test in the second statement:
alpha = myvariable;
The value of the variable myvariable is 500 and is then copied to the variable test.In the third
statement, the address of the variable myvariable denoted by reference operator & myvariable
is assigned to the variable x as:
x = & myvariable;
The address of the variable 3021 and not the contents of the variable myvariable is then copied
into the variable x. The fourth statement makes use of the deference operator:
y=*x
This means that the value pointed to by the pointer variable x gives the value 500 to y.
The programmer must note that the x refers to the address 3021 whereas *x refers to
the value stored in the address 3021 namely 500.
The reference operator is denoted by & and deference operator denoted by *. Both
differ in their meaning and functionality. The reference operator denotes the address of.
The dereference operator denotes the value pointed by. In short, a deference variable
can be denoted as referenced.
If the programmer wants to define more than two pointer variables, then comma
operator may be used in this instance. The programmer must carefully place pointer
symbol * before each pointer variable.
For instance, if the user wishes to define two integer pointer variables, v1 and v2, this can be
done as follows:
int *v1,*v2;
This means that v1 is a pointer variable pointing to integer data type but v2 is only an integer
data type and not a pointer type. The programmer must ensure to place * before each pointer
variable.
The dereferencing or indirect addressing is performed using the indirection operator * used to
access the value stored in an address.
The definition of pointer variable as in the above case is the pointer variable myvar.
It is also possible to assign value to pointer variable using indirection operator. This gives the
same effect as working with variables.
For Example:
#include
void main()
{
int var1,var2;
int *temp;
temp=&var1;
var1=500;
var2=500;
*temp=100;
var2=*temp;
cout<<var1;
cout<<var2;
}
In the above example, the pointer variable temp points to integer variable example and takes
the address of the variable var1 and var1and var2 have initial values of 500.
Sets the value of the variable pointed by pointer variable temp as 100.This is equivalent to
setting var1=100.
Sets the value of variable var2 with the value pointed by the pointer variable temp which is 100.
var2 also becomes 100 and both results are displayed having the value 100.
Q 3: Explain function and different type of parameters passed through the functions?
Ans : A function is a structure that has a number of program statements grouped as a unit with
a name given to the unit. Function can be invoked from any part of the C++ program.
Features of Function:
The piece of code that needs to be executed, or the piece of code that is repeated in different
parts of the program, can be written separately as a function and stored in a place in memory.
Whenever and wherever needed, the programmer can invoke the function and use the code to
be executed. Thus, the program size is reduced. Functions are building blocks of the programs.
They make the programs more modular and easy to read and manage. All C++ programs must
contain the function main( ). The execution of the program starts from the function main( ). A
C++ program can contain any number of functions according to the needs. The general form of
the function is: -
return_type function_name(parameter list)
{
body of the function
}
The function of consists of two parts function header and function body. The function header
is:-
return_type function_name(parameter list)
The return_type specifies the type of the data the function returns. The return_type can be
void which means function does not return any data type. The function_name is the name of
the function. The name of the function should begin with the alphabet or underscore. The
parameter list consists of variables separated with comma along with their data types. The
parameter list could be empty which means the function do not contain any parameters. The
parameter list should contain both data type and name of the variable. For example,
is the function header of the function factorial. The return type is of integer which means
function should return data of type integer. The parameter list contains two variables n and j of
type integer and float respectively. The body of the function performs the computations.
Function Arguments
An argument is the value that is passed from the program to the function call. This can also be
considered as input to the function from the program from which it is called.The information is
transferred to the function by the means of arguments when a call to a function is made.
Arguments contain the actual value which is to be passed to the function when it is called. The
sequence of the arguments in the call of the function should be same as the sequence of the
parameters in the parameter list of the declaration of the function. The data types of the
arguments should correspond with the data types of the parameters. When a function call is
made arguments replace the parameters of the function.
There are two parameter passing mechanisms for passing arguments to functions are:
Pass by value
Pass by reference.
Pass by value
In pass be value mechanism copies of the arguments are created and which are stored in the
temporary locations of the memory. The parameters are mapped to the copies of the
arguments created. The changes made to the parameter do not affect the arguments. Pass by
value mechanism provides security to the calling program. Here is a program which illustrates
the working of pass by value mechanism.
#include<iostream>
using namespace std;
int add(int n);
int main()
{
int number,result;
number=5;
cout << " The initial value of number : " << number << endl;
result=add(number);
cout << " The final value of number : " << number << endl;
cout << " The result is : " << result << endl;
return(0);
}
int add(int number)
{
number=number+100;
return(number);
}
The result of the program is:-
The value of the variable number before calling the function is 5. The function call is made and
function adds 100 to the parameter number. When the function is returned the result contains
the added value. The final value of the number remains same as 5. This shows that operation
on parameter does not produce effect on arguments.
Pass by reference
Pass by reference is the second way of passing parameters to the function. The address of the
argument is copied into the parameter. The changes made to the parameter affect the
arguments. The address of the argument is passed to the function and function modifies the
values of the arguments in the calling function. Here is a program which illustrates the working
of pass by reference mechanism.
#include<iostream>
using namespace std;
int add(int &number);
int main ()
{
int number;
int result;
number=5;
cout << "The value of the variable number before calling the function : " << number << endl;
result=add(&number);
cout << "The value of the variable number after the function is returned : " << number << endl;
cout << "The value of result : " << result << endl;
return(0);
}
int add(int &p)
{
*p=*p+100;
return(*p);
}
The result of the program is:-
The address of the variable is passed to the function. The variable p points to the memory
address of the variable number. The value is incremented by 100. It changes the actual
contents of the variable number. The value of variable number before calling the function is
100 and after the function is returned the value of variable number is changed to 105.
Ans : Structure is a collection of variables under a single name. Variables can be of any type: int,
float, char etc. The main difference between structure and array is that arrays are collections of
the same data type and structure is a collection of variables under a single name.
Declaring a Structure:
The structure is declared by using the keyword struct followed by structure name, also called a tag. Then
the structure members (variables) are defined with their type and variable names inside the open and
close braces { and }. Finally, the closed braces end with a semicolon denoted as ; following the
statement. The above structure declaration is also called a Structure Specifier.
Example:
Three variables: custnum of type int, salary of type int, commission of type float are structure
members and the structure name is Customer. This structure is declared as follows:
In the above example, it is seen that variables of different types such as int and float are
grouped in a single structure name Customer. Arrays behave in the same way, declaring
structures does not mean that memory is allocated. Structure declaration gives a skeleton or
template for the structure. After declaring the structure, the next step is to define a structure
variable.
This is similar to variable declaration. For variable declaration, data type is defined followed by
variable name. For structure variable declaration, the data type is the name of the structure
followed by the structure variable name.
What happens when this is defined? When structure is defined, it allocates or reserves space in
memory. The memory space allocated will be cumulative of all defined structure members. In
the above example, there are 3 structure members: custnum, salary and commission. Of these,
two are of type in and one is of type float. If integer space allocated by a system is 2 bytes and
float four bytes the above would allocate 2bytes for custnum, 2 bytes for salary and 4 bytes for
commission.
To access structure members, the operator used is the dot operator denoted by (.). The dot
operator for accessing structure members is used thusly:
structure variable name.member name
For example:
A programmer wants to assign 2000 for the structure member salary in the above example of
structure Customer with structure variable cust1 this is written as:
It is perfectly possible to define one structure as part of another. Here's an example - a snooker
table. A snooker table has a length and a width. It also has six pockets, one at each corner and
one in the middle of the longest sides. There are 10 red balls, and one each of the following
colours: white, black, green, yellow, brown, blue and pink, each worth different numbers of
points. Each ball is defined by its position on the table or down one of the pockets.
Defining a position as a structure. This is defined as an x-co-
ordinate (horizontal position) and a y-co-ordinate.
struct position
{ float x,y; };
struct ball
{ position p;
int colour; // 0=black, 1=white etc.
int points;
int status;
};
This contains a reference to the previous structure that we defined. Finally, the table itself is
defined as having 17 balls and 6 pockets. Each pocket is defined solely by its position.
struct table
{ ball balls[17]; // First ball is balls[0]
position pockets[6];
float length,width;
};
table snooker;
The structures within structures are accessed using multiple full stops. The table length is set
using snooker.length = 2.4; and the pocket positions are set using snooker.pockets[0].x = 0; and
snooker.pockets[0].y = 0;. The ball positions are set using even more full stops:
snooker.balls[4].p.x = 1.466; and snooker.balls[4].p.y = 0.782;.
Ans : The copy constructor is a special kind of constructor which creates a new object which is a copy of
an existing one, and does it efficiently. The copy constructor receives an object of its own class as an
argument, and allows creating a new object which is copy of another without building it from scratch.
string s4 = s1;
// object s4 does not activate the constructor, but its copy constructor to make only a copy of s1,
rather than building a new object
you have to use const in the argument at the copy constructor to create an object as a copy of a
temporary object: e.g. string(const string &s).
to make things clear, you can create a new object as copy of a different object without using a
copy constructor, like this:
string s4;
s4.set(s1);
this is an example of inefficient code. Since s4 first call its constructor to build a new object and
then it make a bit-wise copy of s1. The whole process of calling the constructor to build an
object which next is being rewritten, is wasteful, takes time and resources. Copy constructor
allow you to prevents this inefficiency.
Copy constructor takes one argument. Also called one argument constructor. The main use of
copy constructor is to initialize the objects while in creation, also used to copy an object. The
copy constructor allows the programmer to create a new object from an existing one by
initialization.
For Example:
#include <iostream.h>
class Tempvar ()
{
private:
int a;
public:
Tempvar ()
{ }
Tempvar (int w)
{
a=w;
}
Tempvar (Tempvar & e)
{
a=e.a;
cout<<” Example of Copy Constructor”;
}
void result()
{
cout<< a;
}
};
void main()
{
Tempvare1(50);
Tempvare3(e1);
cout<< “\ne3=”;e3.result();
}
In the above the copy constructor takes one argument an object of type Tempvar which is
passed by reference. The output of the above program is
The keyword friend is placed only in the function declaration of the friend function and
not in the function definition.
It is possible to declare a function as friend in any number of classes.
When a class is declared as a friend, the friend class has access to the private data of the
class that made this a friend.
A friend function, even though it is not a member function, would have the rights to
access the private members of the class.
It is possible to declare the friend function as either private or public.
The function can be invoked without the use of an object. The friend function has its
argument as objects, seen in example below.
#include
class Tempvar
{
private:
int a,b;
public:
void test()
{
a=100;
b=200;
}
friend int compute(Tempvar e1)
//Friend Function Declaration with keyword friend and with the object of class
Tempvar to which it is friend passed to it
};
main()
{
Tempvar e;
e.test();
cout<<"The result is:"<
//Calling of Friend Function with object as argument.
}
The function compute() is a non-member function of the class Tempvar. In order to make this
function have access to the private data a and b of class Tempvar, it is created as a friend
function for the class Tempvar. As a first step, the function compute() is declared as friend in
the class Tempvar as:
The keyword friend is placed before the function. The function definition is written as a normal
function and thus, the function has access to the private data a and b of the class Tempvar. It is
declared as friend inside the class, the private data values a and b are added, 5 is subtracted
from the result, giving 295 as the result. This is returned by the function and thus the output is
displayed as shown above.
Ans: In C++ the overloading principle applies not only to functions, but to operators too. That is,
the meaning of operators can be extended from built-in types to user-defined types. In this way
a programmer can provide his or her own operator to a class by overloading the built-in
operator to perform some specific computation when the operator is used with objects of that
class.
Some programmers consider that overloading is not useful most of the time. This and the fact
that overloading makes the language more complicated is the main reason why operator
overloading is banned in Java. Even if overloading adds complexity to the language it can
provide a lot of syntactic sugar, and code written by a programmer using operator overloading
can be easy, but sometimes misleading, to read. We can use operator overloading easily
without knowing all the implementation's complexities. A short example will make things clear:
Complex c = a+b; //for this to work the addition operator must be overloaded
The addition without having overloaded operator + could look like this:
a.Add(b);
Complex c(a);
This piece of code is not as suggestive as the first one and the readability becomes poor. Using
operator overloading is a design decision, so when we deal with concepts where some operator
seems fit and its use intuitive, it will make the code more clear than using a function to do the
task. However, there are many cases when programmers abuse this technique, when the
concept represented by the class is not related to the operator (like using + and - to add and
remove elements from a data structure). In this cases operator overloading is a bad idea,
creating confusion.
In order to be able to write the above code we must have the "+" operator overloaded to make
the proper addition between the real members and the imaginary ones and also the
assignment operator. The overloading syntax is quite simple, similar to function overloading,
the keyword operator followed by the operator we want to overload as you can see in the next
code sample:
class Complex
{
public:
Complex(double re,double im)
:real(re),imag(im)
{};
Complex operator+(Complex);
Complex operator=(Complex);
private:
double real;
double imag;
}
Complex Complex::operator+(Complex num)
{
real = real + num.GetRealPart();
imag = imag + num.GetImagPart();
return *this;
}
The assignment operator can be overloaded similarly. Notice that we had to call the accessor
function in order to get the real and imaginary parts from the parameter since they are private.
In order to bypass this difficulty we could have made the operator + a friend (a friend function
is a function which is permitted to access the private members of a class) in the complex class:
We could have defined the addition operator globally and called a member to do the actual
work:
Complex operator+(Complex &num1,Complex &num2)
{
Complex temp(num1); //note the use of a copy constructor here
temp.Add(num2);
return temp;
}
The motivation for doing so can be understood by examining the difference between the two
choices: when the operator is a member the first object in the expression must be of that
particular type, when it's a global function, the implicit or user-defined conversion can allow the
operator to act even if the first operand is not exactly of the same type:
Complex c = 2+b; //if the integer 2 can be converted by the Complex class, this expression is valid
The number of operands can't be overridden, that is, a binary operator takes two operands, a
unary only one. The same restriction acts for the precedence too, for example the
multiplication takes place before addition. There are some operators that need the first
operand to be left value: operator=, operator(), operator[] and operator->, so their use is
restricted just as member functions(non-static), they can't be overloaded globally. The
operator=, operator& and operator, (sequencing) have already defined meanings by default for
all objects, but their meanings can be changed by overloading or erased by making them
private.
Another intuitive meaning of the "+" operator from the STL string class which is overloaded to
do concatenation:
string prefix("de");
string word("composed");
string composed = prefix+word;
Using "+" to concatenate is also allowed in Java, but note that this is not extensible to other
classes, and it's not a user defined behavior. Almost all operators can be overloaded in C++:
+ - * / % ^ & |
~ ! , = < > <= >=
++ -- << >> == != && ||
+= -= /= %= ^= & = |= *=
<<= >>= [ ] ( ) -> ->* new delete
exceptions are the operators for scope resolution (::), member selection (.), and member
selection through a pointer to a function(.*). Overloading assumes you specify a behavior for an
operator that acts on a user defined type and it can't be used just with general pointers. The
standard behavior of operators for built-in (primitive) types cannot be changed by overloading,
that is, you can't overload operator+(int,int).
The logic(boolean) operators have by the default a short-circuiting way of acting in expressions
with multiple boolean operations. This means that the expression:
will not evaluate all three operations and will stop after a false one is found. This behavior does
not apply to operators that are overloaded by the programmer.
Even the simplest C++ application, like a "hello world" program, is using overloaded operators.
This is due to the use of this technique almost everywhere in the standard library (STL). Actually
the most basic operations in C++ are done with overloaded operators, the IO(input/output)
operators are overloaded versions of shift operators(<<, >>). Their use comes naturally to many
beginning programmers, but their implementation is not straightforward. However a general
format for overloading the input/output operators must be known by any C++ developer. We
will apply this general form to manage the input/output for our Complex class:
Notice the use of the friend keyword in order to access the private members in the above
implementations. The main distinction between them is that the operator>> may encounter
unexpected errors for incorrect input, which will make it fail sometimes because we haven't
handled the errors correctly. A important trick that can be seen in this general way of
overloading IO is the returning reference for istream/ostream which is needed in order to use
them in a recursive manner:
Complex a(2,3);
Complex b(5.3,6);
cout<<