preprocessors in c++

The preprocessors are the directives, which give instruction to the compiler to preprocess the information before actual compilation starts.

All preprocessor directives begin with #, and only white-space characters may appear before a preprocessor directive on a line. Preprocessor directives are not C++ statements, so they do not end in a semicolon (;). We already know #include directive.

Different preprocessor directives (commands) perform different tasks. We can categorize the Preprocessor Directives as follows:
– Inclusion Directives- Macro Definition Directives- Conditional Compilation DirectivesInclusion Directive
This category has only one directive, which is called #include. This inclusion directive is used to include files into the current file. The inclusion directive can be used as follows:
#include <stdio.h>
includes stdio.h from include folder
#include<iostream>
includes cpp class library header iostream
#include<my.cpp>
includes my.cpp file from include folder
#include ”my.h”
includes my.h file from current working folder

Macro Definition Directives
These are used to define macros, which are one, or more program statements (like functions) and they are expanded inline.
There are two directives for Macro Definition:
#define – Used to define a macro
#undef – Used to undefine a macro (The macro cannot be used after it is undefined.)

Conditional Compilation Directives
Conditional Compilation Directives these are used to execute statements conditionally for:
– Executing the code on different machine architectures.
– Debugging purposes.
– Macros can be dependent on other macros (must be defined before they are used.)
– Evaluating codes, which are to be executed depending upon the requirements of the programmer.

The following directives are included in this category:
#if
#elif
#endif
#ifdef
#ifndef


Note: These macros are evaluated on compile time. Therefore they can only use the predefined macros or literals. Most compilers do not support the use of variables with these directives.

templates in c++

Templates in C++ programming allows function or class to work on more than one data type at once without writing different codes for different data types. Templates are often used in larger programs for the purpose of code reusability and flexibility of program. The concept of templetes can be used in two different ways:

– Function Template
– Class Template

Function Template
A function templates work in similar manner as function but with one key difference. A single function template can work on different types at once but, different functions are needed to perform identical task on different data types.

The general form of a template function definition is shown here:
template <class type> ret-type func-name(parameter list)
{
// body of function
}


Here, type is a placeholder name for a data type used by the function. This name can be used within the function definition.

Class Template
Just as we can define function templates, we can also define class templates. The general form of a generic class declaration is shown here:

template <class type> class class-name {


.
}


Here, type is the placeholder type name, which will be specified when a class is instantiated. You can define more than one generic data type by using a comma-separated list.

dynamic memory in c++

Allocating memory


There are two ways that memory gets allocated for data storage:
Compile Time (or static) Allocation
– Memory for named variables is allocated by the compiler
– Exact size and type of storage must be known at compile time
– For standard array declarations, this is why the size has to be constant

Dynamic Memory Allocation
– Memory allocated “on the fly” during run time
– dynamically allocated space usually placed in a program segment known as the heap or the free store.
– Exact amount of space or number of items does not have to be known by the compiler in advance.
– For dynamic memory allocation, pointers are crucial.

Dynamic Memory Allocation

We can dynamically allocate storage space while the program is running, but we cannot create new variable names “on the fly”

For this reason, dynamic allocation requires two steps:
– Creating the dynamic space.
– Storing its address in a pointer (so that the space can be accesed)

To dynamically allocate memory in C++, we use the new operator.

De-allocation:
– Deallocation is the “clean-up” of space being used for variables or other data storage
– Compile time variables are automatically deallocated based on their known extent (this is the same as scope for “automatic” variables)
– It is the programmer’s job to deallocate dynamically created space
– To de-allocate dynamic memory, we use the delete operator

Allocating space with new

To allocate space dynamically, use the unary operator new, followed by the type being allocated.

new int;
// dynamically allocates an int 
new double;
// dynamically allocates a double

If creating an array dynamically, use the same form, but put brackets with a size after the type:
new int[40];
// dynamically allocates an array of 40 ints 
new double[size];
// dynamically allocates an array of size doubles

These statements above are not very useful by themselves, because the allocated spaces have no names! BUT, the new operator returns the starting address of the allocated space, and this address can be stored in a pointer:
int * p;
// declare a pointer p 
p = new int;
// dynamically allocate an int and load address into p

Deallocation of dynamic memory

To deallocate memory that was created with new, we use the unary operator delete. The one operand should be a pointer that stores the address of the space to be deallocated:
int * ptr = new int;
// dynamically created int

delete ptr;
// deletes the space that ptr points to

Note that the pointer ptr still exists in this example. That’s a named variable subject to scope and extent determined at compile time. It can be reused:
ptr = new int[10];
// point p to a brand new array

To deallocate a dynamic array, use this form:
delete [] name_of_pointer;

exceptions handling in c++

Exceptions provide a way to react to exceptional circumstances (like runtime errors) in our program by transferring control to special functions called handlers.

C++ exception handling is built upon three keywords: try, catch, and throw.

throw: A program throws an exception when a problem shows up. This is done using a throw keyword.
catch: A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The catch keyword indicates the catching of an exception.
try: A try block identifies a block of code for which particular exceptions will be activated. It’s followed by one or more catch blocks.

Assuming a block will raise an exception, a method catches an exception using a combination of the try and catch keywords. A try/catch block is placed around the code that might generate an exception. Code within a try/catch block is referred to as protected code, and the syntax for using try/catch looks like the following:

try
{
// protected code
}catch( ExceptionName e1 )
{
// catch block
}catch( ExceptionName e2 )
{
// catch block
}catch( ExceptionName eN )
{
// catch block
}

You can list down multiple catch statements to catch different type of exceptions in case your try block raises more than one exception in different situations.

Throwing Exceptions
Exceptions can be thrown anywhere within a code block using throw statements. The operand of the throw statements determines a type for the exception and can be any expression and the type of the result of the expression determines the type of exception thrown.

Following is an example of throwing an exception when dividing by zero condition occurs:
double division(int a, int b)
{
if( b == 0 )
{
throw “Division by zero condition!”;
}
return (a/b);
}

Catching Exceptions
The catch block following the try block catches any exception. You can specify what type of exception you want to catch and this is determined by the exception declaration that appears in parentheses following the keyword catch.

try
{
// protected code
}catch( ExceptionName e )
{
// code to handle ExceptionName exception
}

C++ Standard Exceptions
std::exception – An exception and parent class of all the standard C++ exceptions.
std::bad_alloc – This can be thrown by new.
std::bad_cast – This can be thrown by dynamic_cast.
std::bad_exception – This is useful device to handle unexpected exceptions in a C++ program
std::bad_typeid – This can be thrown by typeid.
std::logic_error – An exception that theoretically can be detected by reading the code.
std::domain_error – This is an exception thrown when a mathematically invalid domain is used
std::invalid_argument – This is thrown due to invalid arguments.
std::length_error – This is thrown when a too big std::string is created
std::out_of_range – This can be thrown by the at method from for example a std::vector and std::bitset < >::operator[]().
std::runtime_error – An exception that theoretically can not be detected by reading the code.
std::overflow_error – This is thrown if a mathematical overflow occurs.
std::range_error – This is occured when you try to store a value which is out of range.
std::underflow_error – This is thrown if a mathematical underflow occurs.

Define your own exceptions
You can define your own exceptions by inheriting and overriding exception class functionality.
eg.
struct MyException : public exception
{
const char * display() const throw ()
{
return “This is Exception”;
}
};

Here, what() is a public method provided by exception class and it has been overridden by all the child exception classes. This returns the cause of an exception.

file handling in c++

A file is collection of related records, a record is composed of several fields and field is a group of character.

This requires another standard C++ library called fstream which defines three new data types:
– Ofstream
This data type represents the output file stream and is used to create files and to write information to files.
– Ifstream
This data type represents the input file stream and is used to read information from files.
– Fstream
This data type represents the file stream generally, and has the capabilities of both ofstream and ifstream which means it can create files, write information to files, and read information from files.

File Operations
1.Open an existing file
2.Read from file
3.Write to a file
4.Moving a specific location in a file(Seeking)
5.Closing File

Opening a File
A file must be opened before you can read from it or write to it. Either the ofstream or fstream object may be used to open a file for writing and ifstream object is used to open a file for reading purpose only.Following is the standard syntax for open() function, which is a member of fstream, ifstream, and ofstream objects.

void open(const char *filename, ios::openmode mode);

Here, the first argument specifies the name and location of the file to be opened and the second argument of the open() member function defines the mode in which the file should be opened.

file open modes
ios::app – Append mode. All output to that file to be appended to the end.
ios::ate – Open a file for output and move the read/write control to the end of the file.
ios::in – Open a file for reading.
ios::out – Open a file for writing.
ios::trunk – If the file already exists, its contents will be truncated before opening the file.

Closing a File
When a C++ program terminates, it automatically closes flushes all the streams, release all the allocated memory and close all the opened files. But it is always a good practice that a programmer should close all the opened files before program termination.
Following is the standard syntax for close() function, which is a member of fstream, ifstream, and ofstream objects.

void close();

Writing to a File
While doing C++ programming, you write information to a file from your program using the stream insertion operator (<<) just as you use that operator to output information to the screen. The only difference is that you use an ofstream or fstream object instead of the cout object.

Reading from a File
You read information from a file into your program using the stream extraction operator (<<) just as you use that operator to input information from the keyboard. The only difference is that you use an ifstream or fstream object instead of the cin object.

File Position Pointers
Both istream and ostream provide member functions for repositioning the file-position pointer. These member functions are seekg (“seek get”) for istream and seekp (“seek put”) for ofstream.The argument to seekg and seekp normally is a long integer. A second argument can be specified to indicate the seek direction. The seek direction can be ios::beg (the default) for positioning relative to the beginning of a stream, ios::cur for positioning relative to the current position in a stream or ios::end for positioning relative to the end of a stream.

data encapsulation in c++

Encapsulation is the method of combining the data and functions inside a class. This hides the data from being accessed from outside a class directly, only through the functions inside the class is able to access the information.


This is also known as “Data Abstraction”, as it gives a clear separation between properties of data type and the associated implementation details. There are two types, they are “function abstraction” and “data abstraction”. Functions that can be used without knowing how its implemented is function abstraction. Data abstraction is using data without knowing how the data is stored.

C++ supports the properties of encapsulation and data hiding through the creation of user-defined types, called classes. We know that class can have private, protected and public members. By default, all items defined in a class are private. For example:class add{public:double getadd(void){return no1 + no2;}private:double no1; double no2;};The variables no1 & no2 are private. This means that they can be accessed only by other members of the add class, and not by any other part of your program. This is one way encapsulation is achieved.

To make parts of a class public (i.e., accessible to other parts of your program), you must declare them after the public keyword. All variables or functions defined after the public specifier are accessible by all other functions in your program.

Making one class a friend of another exposes the implementation details and reduces encapsulation. The ideal is to keep as many of the details of each class hidden from all other classes as possible.

data abstraction in c++

Object Oriented Programming has a special feature called data abstraction. Data abstraction allows ignoring the details of how a data type is represented. While defining a class, both member data and member functions are described. However while using an object (that is an instance of a class) the built in data types and the members in the class are ignored. This is known as data abstraction. This can be seen from the above example.


Benefits of Data Abstraction

– Class internals are protected from inadvertent user-level errors, which might corrupt the state of the object.
– The class implementation may evolve over time in response to changing requirements or bug reports without requiring change in user-level code.

By defining data members only in the private section of the class, the class author is free to make changes in the data. If the implementation changes, only the class code needs to be examined to see what affect the change may have. If data are public, then any function that directly accesses the data members of the old representation might be broken.

Example
#include <iostream.h>
#include <conio.h>

class base{
private: int s1,s2;

public: void inp_val()
{
cout <<“input the values of s1 and s2 “;
cin>>sl>>s2;
}

void display()
{
cout <<s1 <<” “<<s2<<“\n “;
}
};

void main(){
base b;
b.inp_val();
b.display();


Above class takes numbers from user, and returns both. The public members inp_val and display are the interfaces to the outside world and a user needs to know them to use the class. The private members s1 & s2 are something that the user doesn’t need to know about, but is needed for the class to operate properly.

polymorphism & virtual function in c++

Polymorphism

“Poly” means “many” and “morph” means “form”. Polymorphism is the ability of an object (or reference) to assume (be replaced by) or become many different forms of object. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.

C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.Example: function overloading, virtual functions. Another example can be a plus + sign, used for adding two integers or for using it to concatenate two strings. 

Virtual Function:
A virtual function is a function in a base class that is declared using the keyword virtual. Defining in a base class a virtual function, with another version in a derived class, signals to the compiler that we don’t want static linkage for this function.
What we do want is the selection of the function to be called at any given point in the program to be based on the kind of object for which it is called. This sort of operation is referred to as dynamic linkage, or late binding.

class Shape {
protected:
int width, height;

public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}

// pure virtual function
virtual int area() = 0;
};

Important Points to Remember
1. Only the Base class Method’s declaration needs the Virtual Keyword, not the definition.
2. If a function is declared as virtual in the base class, it will be virtual in all its derived classes.
3. The address of the virtual Function is placed in the VTABLE and the copiler uses VPTR(vpointer) to point to the Virtual Function.

operator overloading in c++

Operator overloading is an important concept in C++. It is a type of polymorphism in which an operator is overloaded to give user defined meaning to it. Overloaded operator is used to perform operation on user-defined data type.


Overloaded operators are functions with special names the keyword operator followed by the symbol for the operator being defined. Like any other function, an overloaded operator has a return type and a parameter list.

Almost any operator can be overloaded in C++. However there are few operator which can not be overloaded. Operator that are not overloaded are follows
– scope operator – ::
– sizeof
– member selector – .
– member pointer selector – *
– ternary operator – ?:

Syntax
Return_type class_name :: operator operator_symbol(argument_list)
{
//function body
}


here operator is keyword and operator_symbol is operator to be overloaded.

Implementing Operator Overloading
Operator overloading can be done by implementing a function which can be :
Member Function
Non-Member Function
Friend Function

Operator overloading function can be a member function if the Left operand is an Object of that class, but if the Left operand is different, then Operator overloading function must be a non-member function.
Operator overloading function can be made friend function if it needs access to the private and protected members of class.

Restrictions on Operator Overloading
Following are some restrictions to be kept in mind while implementing operator overloading.

– Precedence and Associativity of an operator cannot be changed.
– Arity (numbers of Operands) cannot be changed. Unary operator remains unary, binary remains binary etc.
– No new operators can be created, only existing operators can be overloaded.
– Cannot redefine the meaning of a procedure. You cannot change how integers are added.

function overloading in c++

You can have multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument list. You can not overload function declarations that differ only by return type.


// overloading functions
#include <iostream.h>
using namespace std;

int add (int a, int b)
{
return (a+b);
}

double add (double a, double b)
{
return (a+b);
}

int main ()
{
int x=5,y=2;
double n=5.0,m=2.5;

cout << add(x,y) << ‘\n’;
cout << add(n,m) << ‘\n’;
return 0;
}

o/p:
7
7.5

In this example, there are two functions called add, but one of them has two parameters of type int, while the other has them of type double. The compiler knows which one to call in each case by examining the types passed as arguments when the function is called. If it is called with two int arguments, it calls to the function that has two int parameters, and if it is called with two doubles, it calls the one with two doubles.

Note that a function cannot be overloaded only by its return type. At least one of its parameters must have a different type.