You are on page 1of 116

C++ Topics

1. C++ Basic Concepts.

1.1 cin.

1.2 cout.

1.3 Reference Variable.

2. Classes.

3. More on Classes.

3.1 Member Functions.

3.2 Data Members.

3.3 Namespaces.

3.4 Friend Class.

3.5 Default Member functions of a class

4. Constructors & Destructors.

4.1 Copy constructors

4.2 Assignment

4.3 Constructors

4.4 Destructors
5. Inheritance.

6. Polymorphism.

6.1 Compile time

6.1.1 Function overloading

6.1.2 Function overriding

6.1.3 Operator overloading

6.2 Run time

6.2.1 Virtual functions

6.2.2 Virtual Base Class

6.2.3 Virtual Destructors

7. Exception Handling.

8. RTTI.

8.1 typeid

8.2 Typecasting.

8.3 “SET_NEW_HANDLER”

9. Templates.

10. STL.

11. Miscellaneous.
11.1 Smart pointers.

11.2 Hash Table

11.3 Object Slicing

11.4 Array vs STL Vector

11.5 Singleton class

11.6 Zombie objects

11.7 this Pointer

11. 8 Namemangling

11. 9 'asm' Keyword

11.10 extern “C”

12. IO Streams
New : new() = malloc() + constructor()

Delete: delete() = destructor() + free()

3. More on Classes.

3.1 Types of Member Functions.

3.1.1 Nested Member Functions

3.1.2 Overloaded member functions

3.1.3 Member functions with Default arguments

3.1.4 Constant member functions

3.1.5 In-line member functions

3.1.6 Static member functions

3.2 Types of Data Members.

3.2.1 Constant Data member

3.2.2 Mutable Data member

3.2.3 Static data member

3.3 Namespace.

3.4 Friend Class.

4. Constructors & Destructor's


eg1:

#include <iostream>

using namespace std;

class Line

public:

int getLength( void );

Line( int len ); // simple constructor

Line( const Line &obj); // copy constructor

Line& operator=( const Line &obj)

cout << "Copy Assignment allocating ptr." << endl;

ptr = new int;

*ptr = *obj.ptr; // copy the value

return *this;

};

~Line(); // destructor

private:

int *ptr;

};

// Member functions definitions including constructor

Line::Line(int len)

cout << "Normal constructor allocating ptr" << endl;

// allocate memory for the pointer;

ptr = new int;

*ptr = len;

Line::Line(const Line &obj)

cout << "Copy constructor allocating ptr." << endl;

ptr = new int;

*ptr = *obj.ptr; // copy the value

// Line::Line& operator=(const Line &obj)

// {

// cout << "Copy constructor allocating ptr." << endl;

// ptr = new int;


// *ptr = *obj.ptr; // copy the value

// return *this;

// }

Line::~Line(void)

cout << "Freeing memory!" << endl;

delete ptr;

int Line::getLength( void )

return *ptr;

void display(Line obj)

cout << "Length of line : " << obj.getLength() <<endl;

// Main function for the program

int main( )

Line line1(10); // Normal Constructor

Line line2 = line1; // Copy Constructor

line2=line1; // Copy Assignment

//display(line1);

//display(line2);

return 0;

eg2:

#include<iostream>

#include<cstring>

using namespace std;

class String

private:

char *s;

int size;

public:

String(const char *str = NULL); // constructor


~String() { delete [] s; } // destructor

String(const String&); // copy constructor

void print(){cout<< s << endl;} // Function to print string

void change(const char *); // Function to change

};

String::String(const char *str)

size = strlen(str);

s = new char[size+1];

strcpy(s, str);

void String::change(const char *str)

delete [] s;

size = strlen(str);

s = new char[size+1];

strcpy(s, str);

String::String(const String& old_str)

size = old_str.size;

s = new char[size+1];

strcpy(s, old_str.s);

int main()

String str1("GeeksQuiz");

String str2 = str1;

str1.print(); // what is printed ?

str2.print();

str2.change("GeeksforGeeks");

str1.print(); // what is printed now ?

str2.print();

return 0;

}
4.1.1 Explicit Constructors

Whenever you create a constructor that takes one argument, you are also implicitly creating

a conversion from the type of that argument to the type of the class. But there may be

times when you do not want this automatic conversion to take place. For this purpose, C++

defines the keyword explicit.

#include <iostream>

using namespace std;

class myclass {

int a;

public:

myclass(int x) { a = x; }

int geta() { return a; }

};

int main()

myclass ob = 4; // automatically converted into myclass(4)

cout << ob.geta();

return 0;

If you do not want this implicit conversion to be made, you can prevent it by using explicit.

The explicit specifier applies only to constructors. A constructor specified as explicit will

only be used when an initialization uses the normal constructor syntax. It will not perform

any automatic conversion. For example, by declaring the myclass constructor as explicit, the

automatic conversion will not be supplied. Here is myclass( ) declared as explicit.


#include <iostream>

using namespace std;

class myclass

int a;

public:

explicit myclass(int x)

a = x;

int geta() { return a; }

};

Now, only constructors of the form

myclass ob(4);

will be allowed and a statement like

myclass ob = 4; // now in error

will be invalid

4.2 Destructor

4.3 Copy constructors

4.4 Assignment

7. Exception Handling
Standard library exceptions:

8. RTTI

8.1 typeid(obj)

In polymorphism there can be situations in which the type of an object is unknown at

compile time because the precise nature of that object is not determined until the program

is executed. C++ implements polymorphism through the use of class hierarchies, virtual

functions, and base-class pointers. Since base-class pointers may be used to point to

objects of the base class or any object derived from that base, it is not always possible to

know in advance what type of object will be pointed to by a base pointer at any given

moment in time. This determination must be made at run time, using run-time type

identification. To obtain an object's type, use typeid. You must include the header

<typeinfo> in order to use typeid. Its most commonly used form is shown here:

typeid(object) ;

Here, object is the object whose type you will be

// A simple example that uses typeid.


#include <iostream>

#include <typeinfo>

using namespace std;

class myclass1 { // ... };

class myclass2 { // ... };

int main()

int i, j;

float f;

char *p;

myclass1 ob1;

myclass2 ob2;

cout << "The type of i is: " << typeid(i).name()<<endl;

cout<<"The type of f is: " << typeid(f).name()<<endl;

cout<<"The type of p is: " << typeid(p).name()<<endl;

cout<<“Type of ob1 is: " << typeid(ob1).name()<<endl;

cout<<"The type of ob2 is: " << typeid(ob2).name()<<endl;

if(typeid(i) == typeid(j))

cout << "The types of i and j are the same\n";

if(typeid(i) != typeid(f))

cout << "The types of i and f are not the same\n";

if(typeid(ob1) != typeid(ob2))

cout << "ob1 and ob2 are of differing types\n";

return 0;

8.2 Type cast in C++

1. const_cast
const_cast(expression) The const_cast<>() is used to add/remove

const(ness) (or volatile-ness) of a variable.


/*
* Constant member function can't modify its data members. Data members are read only.
* If we want remove constantness
* 1. Remove const key word from member function.
* 2. Use const_cast as shown below.
*/
#include <iostream>
using namespace std;
class A
{
int a=10;
public:
void print(int b)const
{
//a++;
const_cast<A*>(this)->a++;
cout<<a<<endl;
//a=b;
const_cast<A*>(this)->a=b;
cout<<a<<endl;
}
};

int main()
{
cout << "Hello World" << endl;
A a1;
a1.print(20);
return 0;
}

2. static_cast
The dynamic_cast operator carries out a run time check to ensure a valid conversion

,but static_cast operator does no perform such a check. If an invalid conversion takes place

the static_cast operator does not produce any error , but results in erratic output

eg:
#include <iostream>
using namespace std;

class A
{
};

class B: public A
{
int p;
public:
void set_p(const int x)
{
cout<<”Set_p called”<<endl;
p=x;
}
int get_p()
{
return p;
}
};
class C: public A
{
int q;
public:
void set_q(const int y)
{
cout<<”Set_q called”<<endl;
}
int get_q()
{
return q;
}
};

int main()
{
A *aptr;
B b1, *bptr;
C c1,*cptr;
aptr=&b1;
bptr = static_cast<B *>(aptr); // Valid conversion
bptr->set_p(1);
cout<<b1.get_p()<<endl;
aptr=&c1;
bptr = static_cast<B *>(aptr); // invalid conversion, but no error
bptr->set_p(2);
cout<< c1.get_q()<<endl;
return 0;
}

'static_cast' operator performs a non polymorphic cast. It can be used for any standard conversion. As earlier told
it does not perform any run time errors checking. Look at this eg
// Use static_cast.
#include <iostream>
using namespace std;
int main()
{
int i=10;
double d;
d = static_cast<double>(i)/9;
cout << d << endl;
return 0;
}

3. dynamic_cast
Dynamic cast is used to convert pointers and references at run-time, generally for the

purpose of casting a pointer or reference up or down an inheritance chain (inheritance

hierarchy). dynamic_cast(expression) The target type must be a pointer or reference type,

and the expression must evaluate to a pointer or reference. Dynamic cast works only when

the type of object to which the expression refers is compatible with the target type and

the base class has at least one virtual member function. If not, and the type of expression

being cast is a pointer, NULL is returned, if a dynamic cast on a reference fails, a bad_cast

exception is thrown. When it doesn't fail, dynamic cast returns a pointer or reference of

the target type to the object to which expression referred.

4. reinterpret_cast

Reinterpret cast simply casts one type bitwise to another. Any pointer or integral type can

be casted to any other with reinterpret cast, easily allowing for misuse. For instance, with

reinterpret cast one might, unsafely, cast an integer pointer to a string pointer.

dynamic_cast in C++

dynamic_cast in C++ can be used to perform type safe down casting. dynamic_cast

is run time polymorphism. The dynamic_cast operator, which safely converts from a pointer

(or reference) to a base type to a pointer (or reference) to a derived type.

eg 1:
#include <iostream>
using namespace std;
class A
{
public:
virtual void f(){cout << "A::f()" << endl;}
};
class B : public A
{
public:
void f(){cout << "B::f()" << endl;}
};
int main()
{
A a;
B b;
a.f(); // A::f()
b.f(); // B::f()
A *pA = &a;
B *pB = &b;
pA->f(); // A::f()
pB->f(); // B::f()

pA = &b;
//pB = &a; // not allowed
pB = dynamic_cast<B*>(&a); // allowed but it returns NULL

if(pB == NULL)
cout<<"NULL";
return 0;
}

eg 2: dyncast.cpp

#include <iostream>
using namespace std;
class A
{
public:
virtual void print()const {cout << " A\n";}
};
class B
{
public:
virtual void print()const {cout << " B\n";}
};
class C: public A, public B
{
public:
void print()const {cout << " C\n";}
};
int main()
{
A* a = new A;
B* b = new B;
C* c = new C;

a -> print();
b -> print();
c -> print();
b = dynamic_cast< B*>(a); //fails
if (b)
b -> print();
else
cout << "no B\n";
a = c;
a -> print(); //C prints
b = dynamic_cast< B*>(a); //succeeds
if (b)
b -> print();
else
cout << "no B\n";
/*
try
{
b = dynamic_cast< B*>(a); //succeeds
b -> print();
}
catch (std::bad_cast& bc)
{
cout << "no B\n";
}
*/
}

eg3:
// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;
class Base_Class { virtual void dummy() {} };
class Derived_Class: public Base_Class { int a; };
int main ()
{
try
{
Base_Class * ptr_a = new Derived_Class;
Base_Class * ptr_b = new Base_Class;
Derived_Class * ptr_c;

ptr_c = dynamic_cast< Derived_Class *>(ptr_a);


if (ptr_c ==0)
cout<<"Null pointer on first type-cast"<< endl;

ptr_c = dynamic_cast< Derived_Class *>(ptr_b);

if (ptr_c ==0)
cout<<"Null pointer on 2nd type-cast"<< endl;

}
catch (exception& my_ex)
{
cout << "Exception: " << my_ex.what();
}
return 0;
}

8.3 “SET_NEW_HANDLER”

What happens when “new” operator cannot find contiguous block of memory large

enough to hold the desired object? At this point a special function called 'st_new_handler'

is called.

By default “new” operator returns a NULL if it fails to allocate memory. This default

behaviour can be changed i.e. if “new” operator fails to allocate the desired memory for an
object instead returning NULL we could write a function which prints error message and

exits program for debugging purpose.

There is an internal function pointer '_new_handler' which usually contains a NULL

value which is called by “new” when it fails and hence the failed 'new' operator returns a

NULL value. We can point the '_new_handler' function pointer to any user defined function

so that next time when 'new' fails the user defined function is called. To make the

'_new_handler' function pointer to point to some user defined function definition , C++

provides a built in function by name 'set_new_handler()' functon.

Eg:

# include <iostream>

# include <cstdlib>

# include <new>

using namespace std;

int cnt = 0;

void my_handler()

cerr << “Memory exhuasted after “<<cnt<<”allocations<<endl;

exit(1);

int main()

set_new_handler(my_handler);

while(1)

cnt++;

int *p = new int(1000000);

return 0;
}

10. Standard Template Library

The Standard Template Libraries (STL's) are a set of C++ template

classes to provide common programming data structures and functions such

as doubly linked lists (list), paired arrays (map), expandable arrays (vector),

large string storage and manipulation (rope), etc. The STL library is available

from the STL home page. This is also your best detailed reference for all of

the STL class functions available.

Also see our C++ Templates tutorial

STL can be categorized into the following groupings:

Container classes:

Sequences:

vector: (this tutorial) Dynamic array of variables, struct or

objects. Insert data at the end.

(also see the YoLinux.com tutorial on using and STL list

and boost ptr_list to manage pointers.)

deque: Array which supports insertion/removal of elements

at beginning or end of array

list: (this tutorial) Linked list of variables, struct or

objects. Insert/remove anywhere.

Associative Containers:

set (duplicate data not allowed in set), multiset (duplication

allowed): Collection of ordered data in a balanced binary

tree structure. Fast search.


map (unique keys), multimap (duplicate keys allowed):

Associative key-value pair held in balanced binary tree

structure.

Container adapters:

stack LIFO

queue FIFO

priority_queue returns element with highest priority.

String:

string: Character strings and manipulation

rope: String storage and manipulation

bitset: Contains a more intuitive method of storing and

manipulating bits.

Operations/Utilities:

iterator: (examples in this tutorial) STL class to represent

position in an STL container. An iterator is declared to be

associated with a single container class type.

algorithm: Routines to find, count, sort, search, ... elements in

container classes

auto_ptr: Class to manage memory pointers and avoid memory

leaks.

Also see the YoLinux.com GDB tutorial on dereferencing STL containers.

File IO Streams
https://www.codingunit.com/cplusplus-tutorial-file-io-in-cplusplus-text-and-

binary-files

By default, C++ opens the files in text mode.

In the tables below we will see the various steps and operations that can be performed
to use files in C++

1)Creating or opening a file

For writing data

Text Files Binary Files


ofstream out (“myfile.txt”); ofstream out (“myfile.txt”,ios::binary);
or or
ofstream out; ofstream out;
out.open(“myfile.txt”); out.open(“myfile.txt”, ios::binary);

For Appending (adding text at the end of the existing file)

Text Files Binary Files


ofstream out(“myfile.txt”,ios::app); ofstream out
or (“myfile.txt”,ios::app|ios::binary);
ofstream out; or
out.open(“myfile.txt”, ios::app); ofstream out;
out.open(“myfile.txt”, ios::app | ios::binary);

For reading data

Text Files Binary Files


ifstream in (“myfile.txt”); ifstream in (“myfile.txt”, ios::binary);
or or
ifstream in ; ifstream in ;
in.open(“myfile.txt”); in.open(“myfile.txt”, ios::binary);

2) Closing Files (after reading or writing)

ofstream object “out” Ifstream object “in”


out.close(); in.close();

3) Reading / Writing Data to and from files

Data Functions for reading file Function for writing into file
char get(); put();
1 word >>(extraction operator) <<(insertion operator)
>=1 word getline(); <<(insertion operator)
Objects read() write()
Binary data Same as above Same as above

4) Functions that can be used to perform special tasks

Operation function Description


Checking end of file. eof() Used to check eof during
the reading of file
Check if an operation bad() Returns true
fails. if a reading or writing operation fails.

Check if an operation Fail() Returns true


fails. in the same cases as bad(), but also in the case that
a format error
happens.

Checking for opened is_open(); Checks if the file is


file. opened or not, returns true if the file is opened else
false
Number of bytes gcount() Returns count of the
already bytes read from the file
read.
Ignoring characters ignore() Ignores n bytes from the
during file read. file. (get pointer is positioned after n
character)
Checking next peek() Checks the next available
character. character, will not increase the get pointer to next
character.
Random access (only seekg() In case of binary files random access is performed
for seekp() using these functions. They either give or set the
binary files). tellg() position of get and put pointers on the particular
tellp() location

Eg1: Write to filename

#include <fstream>

using namespace std;

int main()

ofstream SaveFile("cpp-home.txt");

SaveFile << "Hello World, from www.cpp-home.com and Loobian!";

SaveFile.close();

return 0;

eg2: Reading a filename

#include <fstream.h>

void main() //the program starts here

ifstream OpenFile("cpp-home.txt");

char ch;

while(!OpenFile.eof())

OpenFile.get(ch);

cout << ch;


}

OpenFile.close();

eg3: Append a file

#include <fstream.h>

void main()

ofstream SaveFile("file1.txt", ios::ate);

SaveFile << "That's new!\n";

SaveFile.close();

eg 4:

#include <fstream.h>

void main()

fstream File("test.txt",ios::in | ios::out);

File << "Hi!"; //put “Hi!” in the file

static char str[10]; //when using static, the array is automatically

//initialized, and very cell NULLed

File.seekg(ios::beg); //get back to the beginning of the file

//this function is explained a bit later

File >> str;

cout << str << endl;

File.close();

eg 5: Using put & get

#include <fstream.h>

void main()
{

fstream File("test_file.txt",ios::out | ios::in | ios::binary);

char ch;

ch='o';

File.put(ch); //put the content of ch to the file

File.seekg(ios::beg); //go to the beginning of the file

File.get(ch); //read one character

cout << ch << endl; //display it

File.close();

eg 6: Using Read & write

#include <fstream.h>

#include <string.h>

void main()

fstream File("test_file.txt",ios::out | ios::in | ios::binary);

char arr[13];

strcpy(arr,"Hello World!"); //put Hello World! into the array

File.write(arr,5); //put the first 5 symbols into the file- "Hello"

File.seekg(ios::beg); //go to the beginning of the file

static char read_array[10]; //I will put the read data, here

File.read(read_array,3); //read the first 3 symbols- "Hel"

cout << read_array << endl; //display them

File.close();

eg 7: Current file pointers

#include <fstream.h>

void main()
{

//if we have "Hello" in test_file.txt

ifstream File("test_file.txt");

char arr[10];

File.read(arr,10);

//this should return 5, as Hello is 5 characters long

cout << File.tellg() << endl;

File.close();

eg 9: Getline

#include <fstream.h>

void main()

//if we have "Hello World" in test_file.txt

ifstream File("test_file.txt");

static char arr[10];

/*read, until one of these happens:

1) You have read 10

2) You met the letter "o"

3) There is new line

*/

File.getline(arr,10,'o');

cout << arr << endl; //it should display "Hell"

File.close();

eg 10:

#include <fstream.h>

void main()
{

//if we have "Hello World" in test_file.txt

ifstream File("test_file.txt");

char ch;

File.get(ch);

cout << ch << endl; //should display "H"

cout << char(File.peek()) << endl; //should display "e"

cout << char(File.peek()) << endl; //should display "e" again

File.get(ch);

cout << ch << endl; //should display "e" again

File.close();

eg 11:

#include <fstream.h>#include <io.h>

void main()

ofstream File;

File.open("delete_test.txt"); //creates the file

File.close();

_unlink("delete_test.txt"); //deletes the file

//tries to open the file, but if it does not exists

//the function will rreturn error ios::failbit

File.open("delete_test.txt",ios::nocreate);

//see if it returned it

if(File.rdstate() == ios::failbit)

cout << "Error...!\n"; //yup,it did

File.close();

}
eg 12:

#include <fstream.h>

void main()

//test_file.txt should have this text- "Hello World"

ifstream File("test_file.txt");

char ch;

File.get(ch);

cout << ch << endl; //it will display "H"

File.putback(ch);

cout << ch << endl; //it will again display "H"

File.get(ch);

cout << ch << endl; //it will display "H" again

File.close();

11.9 'asm' Keyword

To accommodate special situations, C++ provides a "trap door" that allows you to

drop into assembly code at any time, bypassing the C++ compiler entirely. This "trap door" is

the asm statement. Using asm, you can embed assembly language directly into your C++

program. This assembly code is compiled without any modification, and it becomes part of

your program's code at the point at which the asm statement occurs.

The general form of the asm keyword is shown here:

asm ("op-code");

where op-code is the assembly language instruction that will be embedded in your program.

However, several compilers also allow the following forms of asm:

asm instruction ;
asm instruction newline

asm {

instruction sequence

Here, instruction is any valid assembly language instruction. Because of the implementation-

specific nature of asm, you must check the documentation that came with your compiler for

details. At the time of this writing, Microsoft's Visual C++ uses _ _asm for embedding

assembly code. It is otherwise similar to asm. Here is a simple (and fairly "safe") example

that uses the asm keyword:

#include <iostream>

using namespace std;

int main()

asm int 5; // generate intertupt 5

return 0;

Types of errors

1. Syntax error:-

This error occurs due to following reason.

I. Not following the grammatical rules used in declaration of identifier.

II. Not declaring an identifier used in program.

III. Not terminating statement by semicolon.

IV. Not providing equal number of opening and closing braces etc.

These errors can be rectified by the user as it is displayed while compiling the program.
2. Logical error:-

This error won’t be displayed on the screen. However it will lead to display wrong

results. Example: An infinite loop. This error lead to abnormal termination of a program or

infinite loop.

3. Runtime error:-

This error occurs while running a program by displaying the message listed below.

I. Division by 0.

II. Overflow

III. Underflow

3.1 Fatal errors

A fatal error is basically when the executable crashes.

Example 1: The program divided by zero, as in:

int scores = 500;

int num = 0;

int avg;

avg = scores / num;

The program would crash saying:

Floating exception

Example 2: Segmentation faults, Bus errors.

These occur when you try to access memory that your program is not allowed to use

or that doesn't exist in the computer (i.e., there is only so much memory in the

computer).

3.2 Logical errors


4. Linker error

These are errors generated when the executable of the program cannot be

generated. This may be due to wrong function prototyping, incorrect header files.

5. Execution error

These errors occur at the time of execution. Looping and arithmetic errors falls

Data Abstraction in C++

Data abstraction refers to, providing only essential information to the outside world

and hiding their background details, i.e., to represent the needed information in program

without presenting the details.

Data abstraction is a programming (and design) technique that relies on the

separation of interface and implementation.

Data Abstraction Example:

Any C++ program where you implement a class with public and private members is an example

of data abstraction. Consider the following example:

#include <iostream>

using namespace std;

class Adder

public:

//Constructor

Adder(int i = 0)

total = i;

void addNum(int num)

total += num;

int getTotal()

return total;
}

private:

//hidden data from outside

int total;

};

int main()

Adder a;

a.addNum(10);

a.addNum(20);

a.addNum(30);

cout<<”Total”<<a.getTotal()<<endl;

return 0;

Output:

Total 60

Above class adds numbers together, and returns the sum. The public

members addNumand getTotal are the interfaces to the outside world and a user needs to

know them to use the class. The private member total is something that the user doesn't

need to know about, but is needed for the class to operate properly.

Characteristics of abstract class

1. Abstract class cannot be instantiated, but pointers and refrences of Abstract

class type can be created.

2. Abstract class can have normal functions and variables along with a pure virtual

function.

3. Abstract classes are mainly used for Upcasting, so that its derived classes can

use its interface.

4. Classes inheriting an Abstract Class must implement all pure virtual functions, or

else they will become Abstract too.


* Why can't we create Object of Abstract Class ?

When we create a pure virtual function in Abstract class, we reserve a slot for a function in

the VTABLE(studied in last topic), but doesn't put any address in that slot. Hence the

VTABLE will be incomplete. As the VTABLE for Abstract class is incomplete, hence the

compiler will not let the creation of object for such class and will display an errror message

whenever you try to do so.

Virtual base class (Diamond Problem)

Because a class can be an indirect base class to a derived class more than once, C++ provides

a way to optimize the way such base classes work. Virtual base classes offer a way to save

space and avoid ambiguities in class hierarchies that use multiple inheritance. Each non

virtual object contains a copy of the data members defined in the base class. This

duplication wastes space and requires you to specify which copy of the base class members

you want whenever you access them. When a base class is specified as a virtual base, it can

act as an indirect base more than once without duplication of its data members. A single

copy of its data members is shared by all the base classes that use it as a virtual base.

When declaring a virtual base class, the virtual keyword appears in the base lists of the

derived classes. When two or more objects are derived from a common base class, we can

prevent multiple copies of the base class being present in an object derived from those

objects by declaring the base class as virtual when it is being inherited. Such a base class is

known as virtual base class. This can be achieved by preceding the base class’ name with the

word virtual.

Find the below example:

#include<iostream>

using namespace std;

class A

public:

int i;

};

class B : virtual public A


{

public:

int j;

};

class C: virtual public A

public:

int k;

};

class D: public B, public C

public:

int sum;

};

int main()

D ob;

ob.i=10;//unambiguous since only 1 copy of i is inherited.

ob.j = 20;

ob.k = 30;

ob.sum = ob.i + ob.j + ob.k;

cout << “Value of i is : ”<< ob.i<<”\n”;

cout << “Value of j is : ”<< ob.j<<”\n”; cout << “Value of k is :”<< ob.k<<”\n”;

cout << “Sum is : ”<< ob.sum <<”\n”;

return 0;

Singleton class in C++

A class whose number of instances that can be instantiated is limited to one is called a

singleton class. Thus, at any given time only one instance can exist, no more.

Singleton class uses:

The singleton design pattern is used whenever the design requires only one instance of a

class. Some examples:


Application classes. There should only be one application class.

(Note: Please bear in mind, MFC class 'CWinApp' is not implemented as a

singleton class)

Logger classes. For logging purposes of an application there is usually one logger

instance required.

Singleton

Singleton is a creational design pattern.

A design pattern to provide one and only instance of an object.

Make the constructors of the class private.

Store the object created privately.

Provide access to get the instance through a public method.

Can be extended to create a pool of objects.

Singleton example:

#include <iostream>
using namespace std;

// Singleton class

class MySingleton {

public:

static MySingleton* iInstance;

public:

static MySingleton* GetInstance();

private:

// private constructor

MySingleton();

};

MySingleton* MySingleton::iInstance = NULL;

MySingleton::MySingleton()

cout << "In construtor ..." << endl;

MySingleton* MySingleton::GetInstance()
{

if ( iInstance == NULL )

iInstance = new MySingleton();

return iInstance;

void main()

MySingleton* obj;

obj = MySingleton::GetInstance();

OUTPUT:

In construtor ... //(displayed only once)

A Singleton is an elegant way of maintaining global state, but we should always question

whether we need global state. Singleton pattern offers several advantages over global

variables because it does the following:Enforces that only one instance of the class can be

instantiated.Allows control over the allocation and destruction of the object.Provides

thread-safe access to the object's global state.Prevents the global namespace from being

polluting.

Singleton example 2:

#include <iostream>

using namespace std;

class Singleton

public:

static Singleton *getInstance();

private:

Singleton(){}

static Singleton* instance;

};
Singleton* Singleton::instance = 0;

Singleton* Singleton::getInstance()

if(!instance)

instance = new Singleton();

cout << "getInstance(): First instance\n";

return instance;

else

cout << "getInstance(): previous instance\n";

return instance;

int main()

Singleton *s1 = Singleton::getInstance();

Singleton *s2 = Singleton::getInstance();

return 0;

11.6 What are zombie objects in C++?

An object creation of a class is failed before executing its constructor. As a

constructor would not return a value, there is no confirmation that whether the constructor

is executed completely or not.

An object that is freed does not crash the applications. The application debugging is

allowed by making the all states of the object intact.

Encapsulation Vs Abstraction

Encapsulation:--Information hiding.

Abstraction:-- Implementation hiding.


Static Class Members

Static Data Members

Data member is declared both inside shared and outside of it. As mentioned earlier,

this is necessary because the declaration of a inside shared does not allocate storage.

One use of a static member variable is to provide access control to some shared

resource used by all objects of a class. Another interesting use of a static member variable

is to keep track of the number of objects of a particular class type that are in existence.

For example,

#include <iostream>
using namespace std;

class Counter
{
public:

static int count;

Counter()
{
count++;
}
~Counter()

count--;

};

int Counter::count;

void f();

int main(void)
{

Counter o1;
cout << "Objects in existence: ";
cout << Counter::count << "\n";

Counter o2;
cout << "Objects in existence: ";
cout << Counter::count << "\n";

f();
cout << "Objects in existence: ";
cout << Counter::count << "\n";

return 0;

void f()

Counter temp;
cout << "Objects in existence: ";
cout << Counter::count << "\n";
// temp is destroyed when f() returns

This program produces the following output.

Objects in existence: 1
Objects in existence: 2
Objects in existence: 3
Objects in existence: 2

Static Member Functions

Member functions may also be declared as static. There are several

restrictions placed on static member functions. They may only directly refer to other

static members of the class. (Of course, global functions and data may be accessed by

static member functions.). A static member function does not have a this pointer. There

cannot be a static and a non-static version of the same function. A static member function

may not be virtual. Finally, they cannot be declared as const or volatile.

Actually, static member functions have limited applications, but one good use

for them is to "preinitialize" private static data before any object is actually created. For

example, this is a perfectly valid C++ program:

#include <iostream>
using namespace std;

class static_type
{
static int i;

public:
static void init(int x) {i = x;}
void show() {cout << i;}

};

int static_type::i; // define i

int main()

// init static data before object creation


static_type::init(100);

static_type x;
x.show(); // displays 100

return 0;

Passing Objects to Functions

Objects may be passed to functions in just the same way that any other type of variable

can. Objects are passed to functions through the use of the standard call-by- value

mechanism. This means that a copy of an object is made when it is passed to a function.

// Passing an object to a function.


#include <iostream>
using namespace std;

class myclass
{
int i;

public:
myclass(int n);
~myclass();
void set_i(int n) { i=n; }
int get_i() { return i; }

};

myclass::myclass(int n)
{

i = n;

cout << "Constructing " << i << "\n";


}
myclass::~myclass()
{

cout << "Destroying " << i << "\n";


}

void f(myclass ob);

int main()

myclass o(1); // Object is created

f(o); // Object is passed to function f()


cout << "This is i in main: ";
cout << o.get_i() << "\n";

return 0;

void f(myclass ob)


{

ob.set_i(2);

cout << "This is local i: " << ob.get_i();

cout << "\n";


}

This program produces this output:

Constructing 1
This is local i: 2
Destroying 2
This is i in main: 1
Destroying 1

Notice that two calls to the destructor function are executed, but only one call is

made to the constructor function. As the output illustrates, the constructor function is not

called when the copy of o(inmain())is passed to ob(withinf()).

Although the constructor function is not called when an object is passed to a

function, it is necessary to call the destructor when the copy is destroyed. (The copy is

destroyed like any other local variable, when the function terminates.) Remember, a new

copy of the object has been created when the copy is made. This means that the copy could

be performing operations that will require a destructor function to be called when the copy
is destroyed. For example, it is perfectly valid for the copy to allocate memory that

must be freed when it is destroyed. For this reason, the destructor function must be

executed when the copy is destroyed.

Functions Returning Objects

A function may return an object to the caller. For example, this is a valid C++ program:

// Returning objects from a function.


#include <iostream>
using namespace std;

class myclass
{
int i;

public:
void set_i(int n) { i=n; }
int get_i() { return i; }

};

myclass f();

//func prototyope which return object of type myclass

int main()

myclass o;
o = f();

cout << o.get_i() << "\n";


return 0;

myclass f()

myclass x;

x.set_i(1);

return x;

}
When an object is returned by a function, a temporary object is automatically

created that holds the return value. It is this object that is actually returned by

the function. After the value has been returned, this object is destroyed. The destruction

of this temporary object may cause unexpected side effects in some situations. For

example, if the object returned by the function has a destructor that frees dynamically

allocated memory, that memory will be freed even though the object that is receiving the

return value is still using it.

Object Assignment

Assuming that both objects are of the same type, you can assign one object to another. This

causes the data of the object on the right side to be copied into the data of the object on

the left.

// Assigning objects.
#include <iostream>
using namespace std;

class myclass
{
int i;

public:
void set_i(int n) { i=n; }
int get_i() { return i; }

};

int main()

myclass ob1, ob2;

ob1.set_i(99);
ob2 = ob1; // assign data from ob1 to ob2

cout << "This is ob2's i: " << ob2.get_i();

return 0;

}
By default, all data from one object is assigned to the other by use of a bit-by-bit

copy. However, it is possible to overload the assignment operator and define some other

assignment procedure

Arrays of Objects

In C++, it is possible to have arrays of objects. The syntax for declaring and using an object

array is exactly the same as it is for any other type of array. For example, this program

uses a three-element array of objects:

#include <iostream>
using namespace std;

class cl
{
int i;

public:
void set_i(int j) { i=j; }
int get_i() { return i; }

};

int main()

cl ob[3];
int i;

for(i=0; i<3; i++)

ob[i].set_i(i+1);

for(i=0; i<3; i++)


cout << ob[i].get_i() << "\n";

return 0;

This program displays the numbers 1, 2, and 3 on the screen.

#include <iostream>
using namespace std;

class cl
{
int i;
public:
cl(int j) { i=j; } // constructor
int get_i() { return i; }

};

int main()

cl ob[3] = {1, 2, 3}; // initializers


// Also initialisation can be done this way
// cl ob[3] = { cl(1), cl(2), cl(3) };

int i;

for(i=0; i<3; i++)


cout << ob[i].get_i() << "\n";

return 0;

Note: Initialized vs. Uninitialized Arrays

cl(int j) { i=j; } // constructor which requires initializers

cl a[9]; // error, constructor requires initializers

cl() { i=0; } // constructor called for non-initialized arrays

cl(int j) { i=j; } // constructor called for initialized arrays

Pointers to Objects

1. #include <iostream>
using namespace std;

class cl
{
int i;

public:
cl(int j) { i=j; }
int get_i() { return i; }

};

int main()

cl ob(88), *p;

p = &ob; // get address of ob

cout << p->get_i(); // use -> to call get_i()


return 0;

2. #include <iostream>
using namespace std;

class cl
{
int i;

public:
cl() { i=0; }
cl(int j) { i=j; }
int get_i() { return i; }

};

int main()

cl ob[3] = {1, 2, 3};


cl *p;
int i;

p = ob; // get start of array


for(i=0; i<3; i++)

cout << p->get_i() << "\n";

p++; // point to next object


}

return 0;

3.
#include <iostream>
using namespace std;

class cl
{
public:

int i;

cl(int j) { i=j; }
};

int main()

cl ob(1);
int *p;
p = &ob.i; // get address of ob.i

cout << *p; // access ob.i via p

return 0;

Type Checking C++ Pointers

You may assign one pointer to another only if the two pointer types are compatible. For

example, given:

int *pi;

float *pf;

in C++, the following assignment is illegal:

pi = pf; // error -- type mismatch

Of course, you can override any type incompatibilities using a cast, but doing so bypasses C+

+'s type-checking mechanism.

Pointers to Derived Types

#include <iostream>
using namespace std;

class base
{
int i;

public:
void set_i(int num) { i=num; }
int get_i() { return i; }

};

class derived: public base


{
int j;

public:
void set_j(int num) { j=num; }
int get_j() { return j; }
};

int main()

base *bp;
derived d;

bp = &d; // base pointer points to derived object

// access derived object using base pointer


bp->set_i(10);
cout << bp->get_i() << " ";

/* The following won't work. You can't access element of a derived class using a base class
pointer.
bp->set_j(88); // error
cout << bp->get_j(); // error

*/

return 0;

As you can see, a base pointer is used to access an object of a derived class. Although you

must be careful, it is possible to cast a base pointer into a pointer of the derived type to

access a member of the derived class through the base pointer. For example, this is valid C+

+ code:

// access now allowed because of cast

((derived *)bp)->set_j(88);

cout << ((derived *)bp)->get_j();

Pointers to Class Members

The type of pointer that "points" generically to a member of a class, not to a specific

instance of that member in an object.

#include <iostream>
using namespace std;

class cl
{
public:

cl(int i) { val=i; }
int val;
int double_val() { return val+val; }

};

int main()

int cl::*data; // data member pointer


int (cl::*func)(); // function member pointer
cl ob1(1), ob2(2); // create objects

data = &cl::val; // get offset of variable val


func=&cl::double_val;//get offset of function double_val()

cout << "Here are values: ";


cout << ob1.*data << " " << ob2.*data << "\n";

cout << "Here they are doubled: ";


cout << (ob1.*func)() << " ";
cout << (ob2.*func)() << "\n";

return 0;

When you are accessing a member of an object by using an object or a reference (discussed

later in this chapter), you must use the .* operator. However, if you are using a pointer to

the object, you need to use the –>* operator, as illustrated in this version of the preceding

program:

#include <iostream>
using namespace std;

class cl
{
public:

cl(int i) { val=i; }
int val;
int double_val() { return val+val; }

};

int main()

int cl::*data; // data member pointer


int (cl::*func)(); // function member pointer
cl ob1(1), ob2(2); // create objects
cl *p1, *p2;
p1 = &ob1; // access objects through a pointer
p2 = &ob2;

data = &cl::val; // get offset of val


func = &cl::double_val; // get offset of double_val()

cout << "Here are values: ";


cout << p1->*data << " " << p2->*data << "\n";

cout << "Here they are doubled: ";

cout << (p1->*func)() << " ";


cout << (p2->*func)() << "\n";

return 0;

References

A reference is essentially an implicit pointer. There are three ways that a

reference can be used:

as a function parameter.

as a function return value.

as a stand-alone reference.

1. Reference Parameters

It allow you to create functions that automatically use call-by-reference parameter passing.

Call-by-reference passes the address of the argument to the function. By default, C++ uses

call-by-value, but it provides two ways to achieve call-by-reference parameter passing.

1. // Manually create a call-by-reference using a pointer.

#include <iostream>
using namespace std;

void neg(int *i);

int main()
{

int x;

x = 10;
cout << x << " negated is ";

neg(&x);
cout << x << "\n";

return 0;

void neg(int *i)


{

*i = -*i;

2. // Use a reference parameter.


#include <iostream>
using namespace std;

void neg(int &i); // i now a reference

int main()

int x;

x = 10;
cout << x << " negated is ";

neg(x); // no longer need the & operator


cout << x << "\n";

return 0;

void neg(int &i)


{

i = -i; // i is now a reference, don't need *


}

2. Passing References to Objects

when an object is passed as an argument to a function, a copy of that object is made. When

the function terminates, the copy's destructor is called. If for some reason you do not want

the destructor function to be called, simply pass the object by reference. (Later in this
book you will see examples where this is the case.) When you pass by reference, no copy of

the object is made. This means that no object used as a parameter is destroyed when the

function terminates, and the parameter's destructor is not called. For example, try this

program:

#include <iostream>
using namespace std;

class cl
{
int id;

public:
int i;

cl(int i);
~cl();
void neg(cl &o){ o.i = -o.i; }// no temporary created

};

cl::cl(int num)
{

cout << "Constructing " << num << "\n";

id = num;

cl::~cl()

{
cout << "Destructing " << id << "\n";

int main()

cl o(1);

o.i = 10;
o.neg(o);

cout << o.i << "\n";

return 0;

Here is the output of this program:

Constructing 1
-10
Destructing 1

As you can see, only one call is made to cl's destructor function. Had o been passed by

value, a second object would have been created inside neg( ), and the destructor would

have been called a second time when that object was destroyed at the time neg( )

terminated

3. Returning References

A function may return a reference. This has the rather startling effect of allowing a

function to be used on the left side of an assignment statement! For example, consider this

simple program:

#include <iostream>
using namespace std;

char &replace(int i); // return a reference


char s[80] = "Hello There";

int main()

replace(5) = 'X'; // assign X to space after Hello

cout << s;

return 0;

char &replace(int i)
{

return s[i];
}

This program replaces the space between Hello and There with an X. That is, the program

displays HelloXthere. Take a look at how this is accomplished. First, replace( ) is declared

as returning a reference to a character. As replace( ) is coded, it returns a reference to

the element of s that is specified by its argument i. The reference returned by replace( )

is then used in main( ) to assign to that element the character X.

Bitwise copy vs memberwise copy in C++

1. shallow copy = bitwise copy and  deep copy = memberwise copy


The compiler will give us a default copy constructor if needed when we do not provide it.

And this constructor is memberwise copy.

Bitwise copy means copy an whole object directly. Where it will be  used? I don't know,

maybe it is an concept in implementation detail, and memcpy() could be used

to achieve it.

Memberwise copy means copy one member of an object at a time.

Deep Copy = memberwise copy

class MyClass {

int *p;

public:

MyClass() : p(new int) {}

MyClass(MyClass const &) : p(new int) {}

};

int main()

MyClass obj1,obj2;

obj2 = obj1; /* Deep Copy */

C++ always do memberwise copy by default.

What is Shallow Copy?

Shallow copy is a bit-wise copy of an object. A new object is created that has an exact

copy of the values in the original object. If any of the fields of the object are references

to other objects, just the reference addresses are copied i.e., only the memory address is

copied.

In this figure, the MainObject1 have fields "field1" of int type, and "ContainObject1" of

ContainObject type. When you do a shallow copy of MainObject1, MainObject2 is created

with "field3" containing the copied value of "field1" and still pointing to ContainObject1

itself. Observe here and you will find that since field1 is of primitive type, the values of it
are copied to field3 but ContainedObject1 is an object, so MainObject2 is still pointing to

ContainObject1. So any changes made to ContainObject1 in MainObject1 will reflect in

MainObject2.

What is Deep Copy?

A deep copy copies all fields, and makes copies of dynamically allocated memory pointed to

by the fields. A deep copy occurs when an object is copied along with the objects to which

it refers.

In this figure, the MainObject1 have fields "field1" of int type, and "ContainObject1" of

ContainObject type. When you do a deep copy of MainObject1, MainObject2 is created with

"field3" containing the copied value of "field1" and "ContainObject2" containing the copied

value of ContainObject1.So any changes made to ContainObject1 in MainObject1 will not

reflect in MainObject2.

Copy constructor vs Assignment operator

A a;

A a2=a; //copy constructor call

A a3(a); //copy constructor call

A a4=a2=a1; //assignment operator for a2, the copy ctor for a4

a1=a2; //memberwise copy

Separate Header and Implementation Files

// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template<class T>
class TestTemp
{
public:
TestTemp();
void SetValue( T obj_i );
T Getalue();
private:
T m_Obj;
};
// TestTemp.cpp
#include "TestTemp.h"
template <class T>
TestTemp<T>::TestTemp()
{

template <class T>


void TestTemp<T>::SetValue( T obj_i )
{
}
template <class T>
T TestTemp<T>::Getalue()
{
return m_Obj;
}

The advantages of storing class definition in separate file are

1. The class is reusable

2. The clients of the class know what member functions the class provides, how to call them

and what return types to expect

3. The clients do not know how the class's member functions are implemented.

pointer variable vs reference variable in C++?

Pointers and references are equivalent, except:

A reference is a name constant for an address. You need to initialize the reference

during declaration.

int & iRef; // Error: 'iRef' declared as reference but not initialized

Once a reference is established to a variable, you cannot change the reference to

reference another variable.

To get the value pointed to by a pointer, you need to use the dereferencing operator * (e.g.,

if pNumber is a int pointer, *pNumber returns the value pointed to by pNumber. It is

calleddereferencing or indirection). To assign an address of a variable into a pointer, you

need to use the address-of operator & (e.g., pNumber = &number). On the other hand,


referencing and dereferencing are done on the references implicitly. For example,

if refNumber is a reference (alias) to another int variable, refNumber returns the value of

the variable. No explicit dereferencing operator * should be used. Furthermore, to assign an

address of a variable to a reference variable, no address-of operator & is needed.

/* Pass-by-reference using pointer (TestPassByPointer.cpp) */ #include <iostream>


using namespace std;
void square(int *);
int main()
{
int number = 8;
cout << "In main(): " << &number << endl; // 0x22ff1c
cout << number << endl; // 8
square(&number); // Explicit referencing to pass an address
cout << number << endl; // 64
}

//Function takes an int pointer (non-const)


void square(int * pNumber)
{
cout << "In square(): " << pNumber << endl; // 0x22ff1c
*pNumber *= *pNumber;// Explicit de-referencing to get the value pointed-to
}

/* Pass-by-reference using reference(TestPassByReference.cpp) */


#include <iostream>
using namespace std;
void square(int &);
int main()
{
int number = 8;
cout << "In main(): " << &number << endl; // 0x22ff1c
cout << number << endl; // 8
square(number); // Implicit referencing (without '&')
cout << number << endl; // 64
}

// Function takes an int reference (non-const)


void square(int & rNumber)
{
cout << "In square(): " << &rNumber << endl; // 0x22ff1c
rNumber *= rNumber;//Implicit de-referencing (without '*')
}

Both references and pointers can be used to change local variables of one function

inside another function. Both of them can also be used to save copying of big objects when

passed as arguments to functions or returned from functions, to get efficiency gain.


Despite above similarities, there are following differences between references and

pointers.

References are less powerful than pointers

1) Once a reference is created, it cannot be later made to reference another object; it

cannot be reseated. This is often done with pointers.

2) References cannot be NULL. Pointers are often made NULL to indicate that they are not

pointing to any valid thing.

3) A reference must be initialized when declared. There is no such restriction with pointers

Due to the above limitations, references in C++ cannot be used for implementing data

structures like Linked List, Tree, etc. In Java, references don’t have above restrictions, and

can be used to implement all data structures. References being more powerful in Java, is

the main reason Java doesn’t need pointers.

References are safer and easier to use:

1) Safer: Since references must be initialized, wild references like wild pointers are unlikely

to exist. It is still possible to have references that don’t refer to a valid location

2) Easier to use: References don’t need dereferencing operator to access the value. They

can be used like normal variables. ‘&’ operator is needed only at the time of declaration.

Also, members of an object reference can be accessed with dot operator (‘.’), unlike

pointers where arrow operator (->) is needed to access members.

Together with the above reasons, there are few places like copy constructor argument

where pointer cannot be used. Reference must be used pass the argument in copy

constructor. Similarly references must be used for overloading some operators like ++.

Passing arguments by reference to functions

Advantages of passing by reference:

It allows a function to change the value of the argument, which is sometimes useful.

Otherwise, const references can be used to guarantee the function won’t change the

argument.

Because a copy of the argument is not made, it is fast, even when used with large structs or

classes.

References can be used to return multiple values from a function.


References must be initialized, so there’s no worry about null values.

Disadvantages of passing by reference:

Because a non-const reference cannot be made to an rvalue (e.g. a literal or an expression),

reference arguments must be normal variables.

It can be hard to tell whether a parameter passed by non-const reference is meant to be

input, output, or both. Judicious use of const and a naming suffix for out variables can help.

It’s impossible to tell from the function call whether the argument may change. An

argument passed by value and passed by reference looks the same. We can only tell whether

an argument is passed by value or reference by looking at the function declaration. This can

lead to situations where the programmer does not realize a function will change the value of

the argument.

When to use pass by reference:

When passing structs or classes (use const if read-only).

When you need the function to modify an argument.

When not to use pass by reference:

When passing arrays (use pass by address).

When passing fundamental types (use pass by value).

Vtable, vptr & vfunc

1. Virtual Table is a lookup table of function pointers used to dynamically bind the virtual

functions to objects at runtime.

2. It is not intended to be used directly by the program, and as such there is no

standardized way to access it.

3. Every class that uses virtual functions (or is derived from a class that uses virtual

functions) is given it's own virtual table as a secret data member.

4. This table is set up by the compiler at compile time. A virtual table contains one entry as

a function pointer for each virtual function that can be called by objects of the class.
5. Virtual table stores NULL pointer to pure virtual functions in ABC.

Note: Virtual Table is created even for classes that have virtual base classes. In this case,

the vtable has pointer to the shared instance of the base class along with the pointers to

the classe's virtual functions if any.

vpointer:

This vtable pointer or _vptr, is a hidden pointer added by the Compiler to the base class.

And this pointer is pointing to the virtual table of that particular class. This _vptr is

inherited to all the derived classes. Each object of a class with virtual functions

transparently stores this _vptr.

Programme to get vptr:


#include<iostream>
//#include<conio.h>
using namespace std;
class Base
{
public:
virtual void display() //virtual function
{
cout<<"\nBase : display()..";
}
virtual void goodMorning() //virtual function
{
cout<<"\nBase : Good morning..";
}
};
class Derived:public Base
{
public:
void display() //virtual by default
{
cout<<"\nDerived : display()..";
}
//Derived does not override goodMorning()
};
int main()
{
Derived d1;
int *vptr=(int *)&d1; //vptr points to Derived object
cout<<vptr;
/Virtual pointer is stored in first 2 bytes of object
vptr=(int *)*vptr; //copy virtual pointer (first 2 bytes) into vptr
cout<<vptr;
//Now content of vptr is nothing but address of VTABLE
//call display()
((void (*)()) *vptr )();
//*vptr is address of first virtual function in VTABLE viz. display()
//and we cast VPTR to a function pointer
++vptr; //move 2 bytes ahead
//access second function in Derived's VTABLE viz.Base::goodMorning()
((void (*)()) *vptr )();
//getch();
return 0;
}

class base
{
virtual void funct1(void);
virtual void funct2(void);
};
base b;
/* C++ Compiler internally Does this*/
b.vptr = address of b.vtable;
b.vtable[0]= &base::funct1;
b.vtable[1]= &base::funct2;

VFPTR VFTABLE FUNCTION


b.vfptr -> Vftable[0] -> base::funct1()
Vftable[1] -> base::funct2()

namespace

• using: You are going to use it.

• namespace: To use what? A namespace.

• std:

The std namespace (where features of the C++ Standard Library, suc h as string or vector ,

are declared). A namespace is a declarative region that provides a scope to the identifiers

(the names of types, functions, variables, etc) inside it. Namespaces are used to organize

code into logical groups and to prevent name collisions that can occur especially when your

code base includes multiple libraries. All identifiers at namespace scope are visible to one

another without qualification. Identifiers outside the namespace can access the members by

using the fully qualified name for each identifier, for example std::vector<std::string> vec;,

or else by a using Declaration for a single identifier (using std::string), or a using Directive

(C++) for all the identifiers in the namespace (using namespace std;).

The std namespace is special; it is short for the word "standard." The built in C++ library

routines are kept in the standard namespace. That includes stuff like cout, cin, string,

vector, map, etc. Because these tools are used so commonly, it's popular to add "using

namespace std" at the top of your source code so that you won't have to type the std::
prefix constantly. And because these functions are kept in a namespace, if you really want

to use "vector" as a variable name, you still can. Namespaces give you more freedom to use

short, accurate names. One side note: it is bad manners to put "using namespace"

declarations in header files. It forces all includers of that header file to use that

namespace, which might result in naming ambiguities that are hard to fix. This practice is

called "namespace pollution." Instead, always use the fully prefixed names in header files

(std::string not string) and save the using declarations for the source files. std::cout

searches in std library and get cout

#include <iostream>
int main()
{
std::cout<<"Hello, world!\n";
}

If you don't tell C++ which drawer to look in, it won't find what you want.
#include <iostream>
int main()
{
cout<<"Hello, world!\n";
}

Now, it's somewhat tedious to keep typing std:: in front of everything, so you can also tell C++ to assume what
drawer to look in

#include <iostream>
int main()
{
using std::cout;
cout<<"Hello, world!\n";
}

Creating Namespaces
#include<iostream>
using namespace std;
namespace myconstants
{
const double pi = 3.141592;
}
namespace myshapes
{
double area;
double perimeter;
void AreaOfCircle(double radius)
{
area = myconstants::pi * radius * radius;
}
void PerimeterOfCircle(double radius)
{
perimeter = 2 * myconstants::pi * radius;
}
}
int main(int argc, char * argv[])
{
double r;
cout << endl << "Enter Radius:";
cin >> r;
myshapes::AreaOfCircle(r);
cout << endl << "Area of the Circle is :" << myshapes::area;
myshapes::PerimeterOfCircle(r);
cout << endl << "Perimeter of the Circle is :" << myshapes::perimeter;
}

Using Namespaces

Namespaces are used with the ‘using’ keyword, which makes all the members of the

namespace available inthe current program and the members can be used directly, without

taking reference of the namespace.


#include<iostream>
using namespace std;
namespace mynamespace
{
int i,j;
}
using namespace mynamespace;
int main(int argc, char *argv[])
{
cout<<endl<<i<<","<<j;
}
without the ‘using’ keyword:
#include<iostream>
using namespace std;
namespace mynamespace
{
int i,j;
}
int main(int argc, char *argv[])
{
std::cout<<endl<<mynamespace::i<<","<<mynamespace::j;
}

'inline' function
C++ inline function is powerful concept that is commonly used with classes. If a function is

inline, the compiler places a copy of the code of that function at each point where the

function is

called at compile time. Any change to an inline function could require all clients of the

function to be recompiled because compiler would need to replace all the code once again

otherwise it will continue with old functionality. A function definition in a class definition is

an automatic inline function definition, even without the use of the inline specifier. features

of inline

1.We must keep inline functions small, small inline functions have better efficiency.

2.Inline functions do increase efficiency, but we should not make all the functions inline.

Because if we make large functions inline, it may lead to code bloat, and might affect the

speed too.

3.Hence, it is adviced to define large functions outside the class definition using scope

resolution ::operator, because if we define such functions inside class definition, then they

become inline automatically.

4.Inline functions are kept in the Symbol Table by the compiler, and all the call for such

functions is taken care at compile time.

Limitations of Inline Functions

1. The compiler is unable to perform inlining if the function is too complicated. So we must

avoid big looping conditions inside such functions. In case of inline functions, entire function

body is inserted in place of each call, so if the function is large it will affect speed and

memory badly.

2. Also, if we require address of the function in program, compiler cannot perform inlining

on such functions. Because for providing address to a function, compiler will have to allocate

storage to it. But inline functions doesn't get storage, they are kept in Symbol table.

Compiler may not perform inlining in such circumstances like:

1) If a function contains a loop. (for, while, do-while)

2) If a function contains static variables.

3) If a function is recursive.
4) If a function return type is other than void, and the return statement doesn’t exist in

function body.

5) If a function contains switch or goto statement.

Advantages :-

1. It does not require function calling overhead.

2. It also save overhead of variables push/pop on the stack, while function calling.

3. It also save overhead of return call from a function.

4. It increases locality of reference by utilizing instruction cache.

5. After in-lining compiler can also apply intra-procedural optimization if specified. This is

the

most important one, in this way compiler can now focus on dead code elimination, can give

more stress on branch prediction, induction variable elimination etc..

static_cast
/*
* The static_cast operator can be used for operations such as
* 1. Converting a pointer of a base class to a pointer of a
* derived class,
* 2. Convert numeric data types such as enums to ints or ints to floats.
* However, static_cast conversions are not necessarily
* safe as no run-time type check is done which can cause* casting between incompatible data types(non related
class/objects), for example pointers.
*/

#include <iostream>
using namespace std;
class A
{
};
class B : public A
{
int a=10;
public:
void f(const string b)
{
//cout << "Class B::f()" << endl;
//a=b;
cout << b << endl;
}
};
class C : public A
{
int a=20;
public:
void f(const string b)
{
//cout << "Class C::f()" << endl;
//a=b;
cout << b << endl;
}
};

int main()
{
A a;
B b;
C c;
b.f("Class B");
c.f("Class C");
// B::f()
// C::f()
A *pA = &a;
B *pB = &b;
C *pC = &c;
pB = static_cast<B *>(&a);
pB->f("A 2 B");
pA=pB;
//pC=pA; // Not Allowed, C & A are non related.
pC=static_cast<C *>(pA); // no error: results in errotic
pC->f("B 2 C");
}
Sizeof class objects

There are many factors that decide the size of an object of a class in C++. These factors

are:

1. Size of all non-static data members

2. Order of data members

3. Byte alignment or byte padding

4. Size of its immediate base class

5. The existence of virtual function(s)(Dynamic polymorphism using virtual

functions).

6. Compiler being used

7. Mode of inheritance (virtual inheritance)

http://www.cprogramming.com/tutorial/size_of_class_object.html

Virtual Function

Virtual Function is a function in base class, which is overrided in the derived class, and

which tells the compiler to perform Late Binding on this function.


class Base
//Abstract base class
{
public:
virtual void show() = 0;
};

//Pure Virtual Function


void Base :: show()
//Pure Virtual definition
{
cout << "Pure Virtual definition\n";
}

class Derived:public Base


{
public:
void show()
{
cout<<"Implementationof Virtual Function in Derived class";
}
};
int main()
{
Base *b;
Derived d;
b = &d;
b->show();
}

Also, the Pure Virtual function must be defined outside the class definition. If you will

define it inside the class definition, complier will give an error. Inline pure virtual definition

is Illegal.

* Smart pointer

A smart pointer is an abstract data type that simulates a pointer while providing additional

features, such as automatic memory management or bounds checking. These additional

features are intended to reduce bugs caused by the misuse of pointers while retaining

efficiency. Smart pointers typically keep track of the memory they point to. They may also

be used to manage other resources, such as network connections and file handles. Smart

pointers originated in the C++ programming language.

1. Using smart pointers, we can make pointers to work in way that we don’t need to explicitly

call delete. Smart pointer is a wrapper class over a pointer with operator like * and ->
overloaded. The objects of smart pointer class look like pointer, but can do many things that

a normal pointer can’t like automatic destruction (yes, we don’t have to explicitly use

delete), reference counting and more. The idea is to make a class with a pointer, destructor

and overloaded operators like * and ->. Since destructor is automatically called when an

object goes out of scope, the dynamically allocated memory would automatically deleted (or

reference count can be decremented). Consider the following simple smartPtr class.
Eg:

#include<iostream>
using namespace std;
class SmartPtr
{
int *ptr; // Actual pointer
public:
//Constructor:Referhttp://www.geeksforgeeks.org/g-fact-93/
// for use of explicit keyword
explicit SmartPtr(int *p = NULL) { ptr = p; }
// Destructor
~SmartPtr() { delete(ptr); }
// Overloading dereferencing operator
int &operator *() { return *ptr; }
int *operator ->() { return ptr; }
};

int main()
{
//SmartPtr ptr(new int());
//*ptr = 20;
SmartPtr ptr(new int(20));
cout<<*ptr;
/* We don't need to call delete ptr:when the object
ptr goes out of scope, destructor for it is automatically called and destructor does delete ptr. */
return 0;
}

2. Can we write one smart pointer class that works for all types? Yes, we can use templates

to write a generic smart pointer class. Following C++ code demonstrates the same.

#include<iostream>
using namespace std;
// A generic smart pointer class
template <class T>
class SmartPtr
{
T *ptr; // Actual pointer
public:
// Constructor
explicit SmartPtr(T *p = NULL) { ptr = p; }
// Destructor
~SmartPtr() { delete(ptr); }
// Overloading dereferncing operator
T & operator * ()
{
return *ptr;
}
// Overloding arrow operator so that members of T can be accessed
// like a pointer (useful if T represents a class or struct or
// union type)
T * operator -> ()
{
return ptr;
}
};
int main()
{
SmartPtr<int> ptr(new int());
*ptr = 20;
cout << *ptr;
return 0;
}

Virtual memory

Virtual memory is a feature of an operating system (OS) that allows a computer to

compensate for shortages of physical memory by temporarily transferring pages of data

from random access memory(RAM) to disk storage.

Page fault

A page fault (sometimes called #PF or PF) is a type of interrupt, called trap, raised by

computer hardware when a running program accesses a memory page that is mapped into the

virtual address space, but not actually loaded into main memory. An interrupt that occurs

when a program requests data that is not currently in real memory. The interrupt triggers

the operating system to fetch the data from a virtual memory and load it into RAM. An

invalid page fault or page fault error occurs when the operating system cannot find the data

in virtual memory. This usually happens when the virtual memory area, or the table that

maps virtual addresses to real addresses, becomes corrupt.

A page fault is the sequence of events occurring when a program attempts to access

data (or code) that is in its address space, but is not currently located in the system's RAM.
The operating system must handle page faults by somehow making the accessed data

memory resident, allowing the program to continue operation as if the page fault had never

occurred. In the case of our hypothetical application, the CPU first presents the desired

address (12374) to the MMU. However, the MMU has no translation for this address. So, it

interrupts the CPU and causes software, known as a page fault handler, to be executed. The

page fault handler then determines what must be done to resolve this page fault. It can:

•Find where the desired page resides on disk and read it in (this is normally the case

if the page fault is for a page of code)

•Determine that the desired page is already in RAM (but not allocated to the

current process) and reconfigure the MMU to point to it

•Point to a special page containing nothing but zeros and later allocate a page only if

the page is ever written to (this is called a copy on write page, and is often used for

pages containing zero-initialized data)

•Get it from somewhere else (which is discussed in more detail later)

Swapping

Swapping is exchanging data between the hard disk and the RAM . The Purpose Of Swapping

. So, we can say that the purpose of swapping, or paging, is to access data being stored in

hard disk and to bring it into the RAM so that it can be used by the application program.

Remember that swapping is only necessary when that data is not already in the RAM.While

swapping (writing modified pages out to the system swap space) is a normal part of a

system's operation, it is possible to experience too much swapping. The reason to be wary of

excessive swapping is that the following situation can easily occur, over and over again:

•Pages from a process are swapped

•The process becomes runnable and attempts to access a swapped page

•The page is faulted back into memory(most likely forcing some other processes' pages to

be swapped out)

•A short time later, the page is swapped out again

What is object slicing?


"Slicing" is where you assign an object of a derived class to an instance of a base class,

thereby losing part of the information - some of it is "sliced" away.


For example,
class A
{
int foo;
};
class B : public A
{
int bar;
};
So an object of type B has two data members, foo and bar .
Then if you were to write this:
B b;
A a = b;
Then the information in b about member bar is lost in a .

Copy Constructor

A copy constructor is a member function which initializes an object using another object of

the same class. A copy constructor has the following general function prototype:
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
public:
Point(int x1, int y1) { x = x1; y = y1; }
// Copy constructor
Point(const Point &p2) {x = p2.x; y = p2.y; }
int getX()
{return x; }
int getY()
{return y; }
};
int main()
{
Point p1(10, 15); // Normal constructor is called here
Point p2 = p1; // Copy constructor is called here
// Let us access values assigned by constructors
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
return 0;
}

When is copy constructor called?

In C++, a Copy Constructor may be called in following cases:

1. When an object of the class is returned by value.


2. When an object of the class is passed (to a function) by value as an argument.

3. When an object is constructed based on another object of the same class.

4. When compiler generates a temporary object.

It is however, not guaranteed that a copy constructor will be called in all these cases,

because the C++ Standard allows the compiler to optimize the copy away in certain cases,

one example being the return value optimization (sometimes referred to as RVO).

Source: http://www.geeksforgeeks.org/g-fact-13/

When is user defined copy constructor needed?If we don’t define our own copy constructor,

the C++ compiler creates a default copy constructor for each class which does a member

wise copy between objects. The compiler created copy constructor works fine in general.

We need to define our own copy constructor only if an object has pointers or any run time

allocation of resource like file handle, a network connection..etc.

Copy constructor vs Assignment Operator

Which of the following two statements call copy constructor and which one calls assignment

operator?

MyClass t1=t2;

MyClass t3 = t1; // ---->(1);

t2 = t1; // ---->(2);

1. Copy constructor is called when a new object is created from an existing object, as a copy

of the existing object. Assignment operator is called when an already initialized object is

assigned a new value from another existing object. In the above example (1) calls copy

constrictor and (2) calls assignment operator. See this for

more details

Write an example class where copy constructor is needed?

Following is a complete C++ program to demonstrate use of Copy constructor. In the

following String class,

we must write copy constructor.


#include<iostream>
#include<cstring>
using namespace std;
class String
{
private:
char *s;
int size;
public:
String(const char *str = NULL); // constructor
~String() { delete [] s; }// destructor
String(const String&); // copy constructor
void print() {cout<<s<<endl; } // Function to print string
void change(const char *); // Function to change
};
String::String(const char *str)
{
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}
void String::change(const char *str)
{
delete [] s;
size = strlen(str);
s = new char[size+1];
strcpy(s, str);}
String::String(const String& old_str)
{
size = old_str.size;
s = new char[size+1];
strcpy(s, old_str.s);
}
int main()
{
String str1("GeeksQuiz");
String str2 = str1;
str1.print(); // what is printed ?
str2.print();
str2.change("GeeksforGeeks");
str1.print(); // what is printed now ?
str2.print();
return 0;
}
Array vs STL Vector

std::vector is a template class that encapsulate a dynamic array 1 , stored in the heap, that

grows

and shrinks automatically if elements are added or removed. It provides all the hooks

( begin() , end() , iterators, etc) that make it work fine with the rest of the STL. It also has

several useful methods that let you perform operations that on a normal array would be

cumbersome, like e.g. inserting elements in the middle of a vector (it handles all the work of

moving the following


elements behind the scenes). Since it stores the elements in memory allocated on the heap,

it has some overhead in respect to static arrays. std::array is a template class that

encapsulate a statically-sized array, stored inside the object itself, which means that, if

you instantiate the class on the stack, the array itself will be on the stack. Its size has to

be known at compile time (it's passed as a template parameter), and it cannot grow or

shrink.

It's more limited than std::vector , but it's often more efficient, especially for

small sizes, because in practice it's mostly a lightweight wrapper around a C-style array.

However, it's more secure, since the implicit conversion to pointer is disabled, and it

provides much of the STL-related functionality of std::vector and of the other containers,

so you can use it easily with STL

algorithms & co. Anyhow, for the very limitation of fixed size it's much less flexible than

std::vector .

map vs. hash_map in C++

They are implemented in very different ways. hash_map ( unordered_map in TR1 and Boost;

use those instead) use a hash table where the key is hashed to a slot in the table and the

value is stored in a list tied to that key.map is implemented as a balanced binary search tree

(usually a red/black tree). An unordered_map should give slightly better performance for

accessing known elements of the collection, but a map will have additional useful

characteristics (e.g. it is stored in sorted order, which allows traversal from start to

finish). unordered_map will be faster on insert and delete than a map .

Default (Implicitly Declared) Member functions of a class

1. the compiler will generate a default constructor for you unless you declare any

constructor of your own.

2. the compiler will generate a copy constructor for you unless you declare your own.

3. the compiler will generate a copy assignment operator for you unless you declare your

own.

4. the compiler will generate a destructor for you unless you declare your own.
class Thing
{
public:
Thing();
// default constructor
Thing(const Thing&);
// copy c'tor
Thing& operator=(const Thing&); // copy-assign
~Thing();
// d'tor
// C++11:
Thing(Thing&&);
// move c'tor
Thing& operator=(Thing&&);
// move-assign
};
MyClass fn(); // function returning a MyClass object
MyClass foo; // default constructor
MyClass bar = foo; // copy constructor
MyClass baz = fn(); // move constructor
foo = bar;
// copy assignment
baz = MyClass();
// move assignment

Move constructor and assignment

Similar to copying, moving also uses the value of an object to set the value to another

object. But, unlike copying, the content is actually transferred from one object (the source)

to the other (the destination): the source loses that content, which is taken over by the

destination. This moving only happens when the source of the value is an unnamed object.

Unnamed objects are objects that are temporary in nature, and thus haven't even been

given a name. Typical examples of unnamed objects are return values of functions or type-

casts. Using the value of a temporary object such as these to initialize another object or to

assign its value, does not really require a copy: the object is never going to be used for

anything else, and thus, its value can be moved into the destination object. These cases

trigger the move constructor and move assignments: The move constructor is called when an

object is initialized on construction using an unnamed temporary. Likewise, themove

assignment is called when an object is assigned the value of an unnamed temporary:

// move constructor/assignment
#include <iostream>#include <string>
using namespace std;
class Example6
{
string* ptr;
public:
Example6 (const string& str) : ptr(new string(str)) {}
~Example6 () {delete ptr;}
// move constructor
Example6 (Example6&& x) : ptr(x.ptr) {x.ptr=nullptr;}
// move assignment
Example6& operator= (Example6&& x)
{
delete ptr;
ptr = x.ptr;
x.ptr=nullptr;
return *this;
}
// access content:
const string& content() const
{
return *ptr;
}// addition:
Example6 operator+(const Example6& rhs)
{
return Example6(content()+rhs.content());
}
};
int main ()
{
Example6 foo ("Exam");
Example6 bar = Example6("ple"); // move-construction
foo = foo + bar;
// move-assignment
cout << "foo's content: " << foo.content() << '\n';
return 0;
}

Dequeue vs List

vector:

•Contiguous memory.

•Pre-allocates space for future elements, so extra space required beyond what's necessary

for the

elements themselves.

•Each element only requires the space for the element type itself (no extra pointers).

•Can re-allocate memory for the entire vector any time that you add an element.•Insertions

at the end are constant, amortized time, but insertions elsewhere are a costly O(n).

•Erasures at the end of the vector are constant time, but for the rest it's O(n).

•You can randomly access its elements.

•Iterators are invalidated if you add or remove elements to or from the vector.
•You can easily get at the underlying array if you need an array of the elements.

list:

•Non-contiguous memory.

•No pre-allocated memory. The memory overhead for the list itself is constant.

•Each element requires extra space for the node which holds the element, including pointers

to the

next and previous elements in the list.

•Never has to re-allocate memory for the whole list just because you add an element.

•Insertions and erasures are cheap no matter where in the list they occur.

•It's cheap to combine lists with splicing.

•You cannot randomly access elements, so getting at a particular element in the list can be

expensive.

•Iterators remain valid even when you add or remove elements from the list.

•If you need an array of the elements, you'll have to create a new one and add them all to it,

since

there is no underlying array.Processes vs. Programs

• A process is different than a program.

• Program: Static code and static data.

• Process: Dynamic instance of code and data.

• No one-to-one mapping between programs and processes.

• Can have multiple processes of the same program Example: many users can run “ls” at the

same time.

One program can invoke multiple processes Example: “make” runs many processes to

accomplish its work.

• A program is sometimes referred as passive entity as it resides on a secondary memory.

• A process is sometimes referred as active entity as it resides on the primary memory and

leaves the memory if the system is rebooted.

Process control block (PCB)


Process Control Block (PCB, also called Task Controlling Block,process table, Task Struct, or

Switchframe) is a data structure in the operating system kernel containing the information

needed to manage a particular process.

1. Process state (new, ready, running, waiting, finish ...)

2. CPU registers (e.g., %eip, %eax)

3. Scheduling information

4. Memory-management information

5. Accounting information

6. I/O status information

• The current state of the process i.e., whether it is ready, running, waiting, or whatever.

• Unique identification of the process in order to track "which is which" information.

• A pointer to parent process.

• Similarly, a pointer to child process (if it exists).

• The priority of process (a part of CPU scheduling information).

• Pointers to locate memory of processes.

• A register save area.

• The processor it is running on.7.

What is a zombie?

a zombie processor defunct process is a process that has completed execution (via the exit

system call) but still has an entry in the process table: it is a process in the "Terminated

state".

Zombie is a process state when the child dies before the parent process. In this case the

structural information of the process is still in the process table....... When a program forks

and the child finishes before the parent, the kernel still keeps some of its information

about the child in case the parent might need it - for example, the parent may need to

check the child's exit status. To be able to get this information, the parent calls 'wait()'; In

the interval between the child terminating and the parent calling 'wait()', the child is said to

be a 'zombie' (If you do 'ps', the child will have a 'Z' in its status field to indicate this.)

Zombie : The process is dead but have not been removed from the process table.

How to kill zombie process


A zombie is already dead, so you cannot kill it. To clean up a zombie, it must be waited on by

its

parent, so killing the parent should work to eliminate the zombie. (After the parent dies,

the zombie will be inherited by init, which will wait on it and clear its entry in the process

table.) If your daemon is spawning children that become zombies, you have a bug. Your

daemon should notice when its children die and wait on them to determine their exit status.

kill $(ps -A -ostat,ppid | awk '/[zZ]/{print $2}')


kill -HUP $(ps -A -ostat,ppid | grep -e '[zZ]'| awk '{ print $2 }')
type2:
$ ps aux | grep Z
$
ps -p 20736 -o ppid
PPID
20735
$ kill -17 20735

orphan process

An orphan process is a computer process whose parent process has finished

or terminated, though it remains running itself. In a Unix-like operating

system any orphaned process will be immediately adopted by the special init

system process. Daemon Process . In Unix and other multitasking computer

operating systems, a daemon is a computer program that runs as a

background process, rather than being under the direct control of an

interactive user. Zombies hardly take any memory. Orphans are regular

processes, they can take a lot of memory and cpu cycles.

What is the difference between Swapping and Paging?

Swapping:

Whole process is moved from the swap device to the main memory for

execution. Process size must be less than or equal to the available main

memory. It is easier to implementation and overhead to the system.


Swapping systems does not handle the memory more flexibly as compared to

the paging systems.

Paging:

Only the required memory pages are moved to main memory from the swap

device for execution. Process size does not matter. Gives the concept of the

virtual memory. It provides greater flexibility in mapping the virtual address

space into the physical memory of the machine. Allows more number of

processes to fit in the main memory simultaneously. Allows the greater

process size than the available physical memory. Demand paging systems

handle the memory more flexibly.

What is the difference between UDP and TCP?

TCP is a Transmission Control Protocol.

UDP is a User Datagram Protocol.

There are four major differences between UDP and TCP:

1. TCP can establish a Connection and UDP cannot.

2. TCP provides a stream of unlimited length, UDP sends Small packets.

3.TCP gurantees that as long as you have a connection data sent will arrive at

the destination, UDP provides not guarantee delivery.

4.UDP is faster for sending small amounts of data since no connection setup

is required, the data can be sent in less time then it takes for TCP to

establish a connection.

What is an inode?ext2 and ext3 file systems keep a list of the files they

contain in a table called an inode table. The inode is referenced

by its number. This is unique within a file system.


The inode contains the metadata about files. Among the data stored in the

inode is

File type

File permissions

Link count

User ID number of the file owner and the group ID number of the

associated group

Last modification time

Location of the data on the hard disk

Other metadata about the file

ls -li – view inode number only

stat /etc/passwd – view inode details

Section Numbers

The section numbers of the manual are listed below. While reading

documentation, if you see a

command name followed by a number in parentheses, the number refers to

one of these sections.

For example, man is the documentation of man found in section number1.

Some commands may

have documentation in more than one section, so the numbers after the

command name may direct you to the correct section to find a specific type

of information. The section numbers, and the topics they cover, are as

follows:

section # topic

1 Executable programs or shell commands


2 System calls (functions provided by the kernel)

3 Library calls (functions within program libraries)

4 Special files (usually found in /dev)

5 File formats and conventions eg /etc/passwd

6 Games

7 Miscellaneous (including macro packages and conventions), e.g. man, groff

8 System administration commands (usually only for root)

9 Kernel routines [Non standard]

Link are of two types Soft links (symbolic links ) or Hard link

1.Soft Links (symbolic links )

◦ You can make links for files & folder & you can create link (shortcut) on

different

partition & got different inode number from original.

◦ If real copy is deleted the link will not work.

2.Hard Links

◦ For files only & you cannot create on different partition ( it should be on

same partition )

& got same inode number as original

◦ If the real copy is deleted the link will work ( because it act as original file

What is a Soft Link or Symbolic Link or Symlink ?

• Soft links are very similar to what we say “Shortcut” in windows, is a way

to link to a file or directory.

• Symlinks doesn’t contain any information about the destination file or

contents of the file, instead of


that, it simply contains the pointer to the location of the destination file.

In more technical words, in soft link, a new file is created with a new inode,

which have the pointer to

the inode location of the original file. This can be better explained with a

diagram:

Symbolic links are created with the “ln” command in linux. The syntax of the

command is:

$ ln -s

-s = This flag tells to create a symlink (if you don’t use this it will create a

hard link, which we will talk aboutsoon).

$ ln -s /usr/bin/gedit ~/Desktop/gedit

What is a Hard Link ?


• Hard link is a bit different object when compared to a symlink.

• In softlink a new file and a new Inode is created, but in hard link, only an entry into

directory

structure is created for the file, but it points to the inode location of the original file.

• Which means there is no new inode creation in the hard link which shares same inode

number. This

can be explained like this:

# ln

# ln /usr/bin/gedit ~/Desktop/gedit

When to use Soft Link:

1.Link across filesystems: If you want to link files across the filesystems, you can only use

symlinks/soft

links.

2.Links to directory: If you want to link directories, then you must be using Soft links, as

you can’t create


a hard link to a directory.

When to use Hard Link:

1. Storage Space: Hard links takes very negligible amount of space, as there are no new

inodes created while creating hard links. In soft links we create a file which consumes space

(usually 4KB, depending upon the filesystem)

2. Performance: Performance will be slightly better while accessing a hard link, as you are

directly accessing the disk pointer instead of going through another file.

3. Moving file location: If you move the source file to some other location on the same file

system, the hard link will still work, but soft link will fail.

4. Redundancy: If you want to make sure safety of your data, you should be using hard link,

as in hard link, the data is safe, until all the links to the files are deleted, instead of that in

soft link, you will lose the data if the master instance of the file is deleted.

Soft Links:

•Issue the ln -s [original filename] [link name] command to create a soft link

•Similar to shortcut feature in Windows Operating system

•Original File and Hard Linked file contain different inode values

•Each soft link file points to the original file’s inode

•Any changes to either original file or soft linked file are reflected in the other file

•Benefit – soft linked file can cross different file systems

•Negative – if original file is deleted or moved, the soft link is broken (hanging link)

Hard Links:

• Issue the ln [original filename] [link name] command to create a hard link

• Original File and Hard Linked file contain the same inode value

• Creates a mirror copy of the file

• Any changes to either original file or hard linked file are reflected in the other file

• Benefit – more flexible and remain linked if either the original or hard linked file is moved

• Negative – unable to cross different file systems

Linux Commands to check Hardware information

1. lscpu
The lscpu command reports information about the cpu and processing units. It does

not have any further options or functionality.

2. lshw - List Hardware

A general purpose utility, that reports detailed and brief information about multiple

different hardware units such as cpu, memory, disk, usb controllers, network adapters etc.

Lshw extracts the information from different /proc files.

3. hwinfo - Hardware Information

Hwinfo is another general purpose hardware probing utility that can report detailed

and brief information about multiple different hardware components, and more than

what lshw can report.

4. lspci - List PCI

The lspci command lists out all the pci buses and details about the devices

connected to them. The vga adapter, graphics card, network adapter, usb ports, sata

controllers, etc all fall under this category.

5. lsscsi - List scsi devices

Lists out the scsi/sata devices like hard drives and optical drives.

6. lsusb - List usb buses and device details

This command shows the USB controllers and details about devices connected to

them. By default brief information is printed. Use the verbose option "-v" to print detailed

information about each usb port

7. Inxi

Inxi is a 10K line mega bash script that fetches hardware details from multiple

different sources and commands on the system, and generates a beautiful looking report

that non technical users can read easily.

8. lsblk - List block devices

List out information all block devices, which are the hard drive partitions and other

storage devices like optical drives and flash drives

9. df - disk space of file systems

Reports various partitions, their mount points and the used and available space on

each.

10. Pydf - Python df


An improved df version written in python, that displays colored output that looks

better than df

11. fdisk

Fdisk is a utility to modify partitions on hard drives, and can be used to list out the

partition information as well.

12. mount

The mount is used to mount/unmount and view mounted file systems.

13. free - Check RAM

Check the amount of used, free and total amount of RAM on system with the free

command.

14. dmidecode

The dmidecode command is different from all other commands. It extracts

hardware information byreading data from the SMBOIS data structures (also called DMI

tables).

15. /proc files

Many of the virtual files in the /proc directory contain information about hardware

and configurations.

Here are some of them

# cpu information

$ cat /proc/cpuinfo

# memory information

$ cat /proc/meminfo

$ cat /proc/version

Linux version 3.11.0-12-generic (buildd@allspice) (gcc version 4.8.1

(Ubuntu/Linaro 4.8.1-10ubuntu7) ) #19-Ubuntu SMP Wed Oct 9 16:20:46 UTC 2013

16. hdparm

The hdparm command gets information about sata devices like hard disks.

As a slightly more realistic program in C++: a class in its own header

(IPv4.h) and implementation (IPv4.cpp) and a program which uses the


class functionality. The class converts an IP address in integer format

to the known quad format.

https://www.linuxcounter.net/toolbox/
//IPv4 class
//IPv4.h:
#ifndef IPV4_H
#define IPV4_H
#include <string>
namespace GenericUtils
{
// create a namespace
class IPv4
{ // class definition
public:
IPv4(); ~Ipv4();
std::string IPint_to_IPquad(unsigned long ip);
// member interface
};
} //namespace GenericUtils
#endif
// IPV4_HIPv4.cpp:
#include "Ipv4.h"
#include <string>
#include <sstream>
using namespace std;
// use the namespaces
using namespace GenericUtils;
IPv4::IPv4() {}
// default constructor/destructor
IPv4::~IPv4() {}
string IPv4::IPint_to_IPquad(unsigned long ip)
{
// member implementation
ostringstream ipstr; // use a stringstream
ipstr << ((ip &0xff000000) >> 24) // Bitwise right shift
<< "." << ((ip &0x00ff0000) >> 16)
<< "." << ((ip &0x0000ff00) >> 8)
<< "." << ((ip &0x000000ff));
return ipstr.str();
}

//simplecpp.cpp
#include "Ipv4.h"
#include <iostream>
#include <string>
using namespace std;
int main (int argc, char* argv[])
{
string ipstr; // define variables
unsigned long ipint = 1347861486; // The IP in integer form
GenericUtils::IPv4 iputils;
// create an object of the class
ipstr = iputils.IPint_to_IPquad(ipint);
// call the class member
cout << ipint << " = " << ipstr << endl;
// print the result
return 0;
}

Compile and execute with:

# g++ -c IPv4.cpp simplecpp.cpp

# Compile in objects

# g++ IPv4.o simplecpp.o -o simplecpp.exe # Link objects to final executable# ./simplecpp.exe

1347861486 = 80.86.187.238

Simple Makefile

CC = g++

CFLAGS = -O

OBJS = IPv4.o simplecpp.o

simplecpp: ${OBJS}

${CC} -o simplecpp ${CFLAGS} ${OBJS}

clean:

rm -f ${TARGET} ${OBJS}

fork vs vfork

http://www.badprog.com/unix-gnu-linux-system-calls-difference-between-fork-

and-vfork

The fork() and vfork() syscalls are different.

The fork() syscall generates two identical processes with separate memory.

The vfork() syscall generates two processes that share the same memory.

With vfork() the parent will wait for the child terminates.

The parent inherites from the variables that the program is sharing.

So after the child was called, all variables modified inside the child will still be modified

inside the parent.

## BadproG.com
## Makefile
## Variables
NAME = forkIt
SRC = main.c
OBJ = $(SRC:.c=.o)
CFLAGS
CC
= -Wall -Werror -Wextra -pedantic -ansi -D_BSD_SOURCE
= gcc## Rules
$(NAME) : $(OBJ)
$(CC) $(OBJ) -o $(NAME)
all : $(NAME)
clean :
rm -f $(OBJ)
fclean
: clean
rm -f $(NAME)
re
r
: fclean all
: re
rm -f *~
rm -f *.o

/**
* Badprog.com
* h.h
*/
#ifndef H_H_
#define H_H_
typedef struct s_forky
{
int value;
} t_forky;
#endif /* H_H_ */

/*
* Badprog.com
* main.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "h.h"
int
main()
{
int i;
int status;
pid_t f;
t_forky forky;
forky.value = 0;
i = 0;
status = 1;
f = fork();
if (f < 0){
fprintf(stderr, "Error: %s - fork() < 0 (%d)\n", strerror(errno), f);
}
else if (f > 0)
{
printf("\n===== Begin Parent =====\n\n");
printf("fork() = %d\n", f);
printf("getpid() = %d\n", getpid());
while (i < 10)
{
printf(" Parent - forky.value = %d\n", forky.value);
++forky.value;
++i;
}
}
else
{
printf("\n===== Begin Child =====\n\n");
printf("fork() = %d\n", f);
printf("getpid() = %d\n", getpid());
while (i < 10)
{
printf(" Child - forky.value = %d\n", forky.value);
++forky.value;
++i;
}
}
printf("status = %d\n", status);printf("forky.value = %d\n\n", forky.value);
printf("===== End =====\n\n");
return 0;
}
output:
===== Begin Parent =====
fork() = 18938
getpid() = 18937
Parent - forky.value = 0
Parent - forky.value = 1
Parent - forky.value = 2
Parent - forky.value = 3
Parent - forky.value = 4
Parent - forky.value = 5
Parent - forky.value = 6
Parent - forky.value = 7
Parent - forky.value = 8
Parent - forky.value = 9
status = 1
forky.value = 10
===== End =====
===== Begin Child =====fork() = 0
getpid() = 18938
Child - forky.value = 0
Child - forky.value = 1
Child - forky.value = 2
Child - forky.value = 3
Child - forky.value = 4
Child - forky.value = 5
Child - forky.value = 6
Child - forky.value = 7
Child - forky.value = 8
Child - forky.value = 9
status = 1
forky.value = 10
===== End =====
/**
* Badprog.com
* main.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>#include <string.h>
#include <errno.h>
#include "h.h"
int
main()
{
int i;
int status;
pid_t f;
t_forky forky;
forky.value = 0;
i = 0;
status = 1;
f = vfork();
if (f < 0)
{
fprintf(stderr, "Error: %s - fork() < 0 (%d)\n", strerror(errno), f);
}
else if (f > 0)
{
printf("\n===== Begin Parent =====\n\n");
printf("fork() = %d\n", f);
printf("getpid() = %d\n", getpid());
while (i < 10)
{
printf(" Parent - forky.value = %d\n", forky.value);+
+forky.value;
++i;
}
}
else
{
printf("\n===== Begin Child =====\n\n");
printf("fork() = %d\n", f);
printf("getpid() = %d\n", getpid());
while (i < 10)
{
printf("Child- forky.value = %d\n", forky.value);
++forky.value;
++i;
}
_exit(status);
}
printf("status = %d\n", status);
printf("forky.value = %d\n\n", forky.value);
printf("===== End =====\n\n");
return 0;
}
compiling:
make r ; ./forkIt
output:===== Begin Child =====
fork() = 0
getpid() = 19013
Child - forky.value = 0
Child - forky.value = 1
Child - forky.value = 2
Child - forky.value = 3
Child - forky.value = 4
Child - forky.value = 5
Child - forky.value = 6
Child - forky.value = 7
Child - forky.value = 8
Child - forky.value = 9
===== Begin Parent =====
fork() = 19013
getpid() = 19012
status = 1
forky.value = 10
===== End =====

Fork(): create a completely new process

Clone(): creates a new thread within a processint clone(int (*fn)(void *), void *child_stack,

int flags, void *arg, ... /* pid_t *pid, struct

user_desc *tls ", pid_t *" ctid " */ );"

Unlike fork(2), these calls allow the child process to share parts of its execution context

with the calling process, such as the memory space, the table of file descriptors, and the

table of signal handlers. (Note that on this manual page, "calling process" normally

corresponds to "parent process". But see the description of CLONE_PARENT below.) The

main use of clone() is to implement threads: multiple threads of control in a program that

run concurrently in a shared memory space. When the child process is created with clone(),

it executes the function application fn(arg). (This differs from fork(), where execution

continues in the child from the point of the fork() call.) The fn argument is a pointer to a

function that is called by the child process at the beginning of its execution. The arg

argument is passed to the fn function.


TCP/IP stack

The most common protocol on the internet is the Transmission Control Protocol/Internet

Protocol (TCP/IP). To send data over a TCP/IP network requires four steps or layers:

Layer

Name

Description

Application Encodes the data being sent

Transport Splits the data into manageable chunks, adds port number information Internet

Adds IP addresses stating where the data is from and where it is going Link Adds MAC

address information to specify which hardware device the message came from, and which

hardware device the message is going to Successive encapsulation (wrapping) of application

data descending through the protocol stack before transmission on the local network linko

show you how the TCP/IP stack works we going to use the following data as an example:

Application[edit]

The application layer makes sure that the data is sent in a format that will be

understandable by the recipient. This will mean formatting data to be sent in a standard

way applicable to that application, for

example HTTP, FTP etc. In this case we are going to wrap each piece of data in XML tags.

Transport[edit]

The transport layer looks at the data to be sent and splits it into chunks that can fit into

data packets. It then attaches a number to each, specifying that packet's order, this allows

the recipient to place the data back together correctly at the other end. To each packet it

then attaches a port number dependent on the application being used. For the example we'll

send data to port 60 Splits the data into chunks and adds order number

Adds port numbers

Transport Header

Data

:60 | 1/4 <gospel>Matt</gospel>

:60 | 2/4 <gospel>Mark</gospel>

:60 | 3/4 <gospel>Luke</gospel>


:60 | 4/4 <gospel>John</gospel>

Network/Internet[edit]

The network layer attaches the IP address of the sender, so that the recipient will know

who sent it and who to send a confirmation message to. It must also attach the IP address

of the host that it is sending the data to so it doesn't get lost! In this case we are sending

to 102.231.4.189 and sending from 98.1.232.99. Combined with the port number this creates

asocket that data is being sent from and a socket that data is being sent to, namely

102.231.4.189:60 •Attaches sender IP address

•Attaches destination IP address to create a socket

Network Header

Transport Header

Data

102.231.4.189

98.1.232.99 :60 | 1/4 <gospel>Matt</gospel>

102.231.4.189

98.1.232.99 :60 | 2/4 <gospel>Mark</gospel>

102.231.4.189

98.1.232.99 :60 | 3/4 <gospel>Luke</gospel>

102.231.4.189

98.1.232.99 :60 | 4/4 <gospel>John</gospel>

Link[edit]

Finally the link layer attaches the MAC address of the sender and the recipient, allowing

the packets to be

directed to a specific network interface on the IP Address host machine. In this case the

sender is using a

wireless card with MAC address: 00-17-4F-08-5D-69 and the destination

MAC address is: 11-22-33-44-55

•Attaches sender MAC address

•Attaches destination MAC address


Link Header

Network Header

Transport Header

Data11-22-33-44-55

102.231.4.189

00-17-4F-08-5D-69 98.1.232.99 :60 | 1/4 <gospel>Matt</gospel>

11-22-33-44-55

102.231.4.189

00-17-4F-08-5D-69 98.1.232.99 :60 | 2/4 <gospel>Mark</gospel>

11-22-33-44-55

102.231.4.189

00-17-4F-08-5D-69 98.1.232.99 :60 | 3/4 <gospel>Luke</gospel>

11-22-33-44-55

102.231.4.189

00-17-4F-08-5D-69 98.1.232.99 :60 | 4/4 <gospel>John</gospel>

These four packets can then be sent across the internet holding enough

information for them to:

1.reach their destination (socket from the Network and Transport Layers)

2.find the correct network interface (MAC address from the Link Layer)

3.find the correct service(Port number from the Transport Layer)

4.be reassembled in the correct order (Order information from the

Transport Layer)

5.deliver the intended message (data from the Application Layer)

Combined, the IP address and Port Number make up a what?

Answer :

Socket
What is the MAC Address for in the TCP/IP stack?

A MAC address is a unique identifier assigned to a network device. It is used

by the Link layer to direct messages to a

particular network interface at the designated IP address

Show the steps involved in sending the following data:

• data = Hello (this will fit in one packet)

• from IP = 12.32.72.2 | MAC = 43.65.FF.23

• to IP = 98.125.43.88 | Port = 80 | MAC = A0.3D.EF.00

• Answer :

Application

"Hello"

Transport

:80

1/1

"Hello"

Internet

To=98.125.43.88

From=12.32.72.2

:80

1/1

"Hello"

Link

From MAC = 43.65.FF.23

To MAC = A0.3D.EF.00

To=98.125.43.88
From=12.32.72.2

:80

1/1

"Hello"Convert an IP address to a human-readable string in C


#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
// ...
char buffer[INET6_ADDRSTRLEN];
int err=getnameinfo((struct sockaddr*)&addr,addr_len,buffer,sizeof(buffer),
0,0,NI_NUMERICHOST);
if (err!=0)
{
die("failed to convert address to string (code=%d)",err);
}
printf("Remote address: %s\n",buffer);

Hash Table

Note:

http://proprogramming.org/program-to-implement-hash-tables-c/

http://pumpkinprogrammer.com/2014/06/21/c-tutorial-intro-to-hash-

tables/
#include<iostream>#include<cstdlib>
#include<string>
#include<cstdio>
using namespace std;
const int TABLE_SIZE = 128;
/*
* HashEntry Class Declaration
*/
class HashEntry
{
public:
int key;
int value;
HashEntry(int key, int value)
{
this->key = key;
this->value = value;
}
};
/*
* HashMap Class Declaration
*/
class HashMap
{
private:
HashEntry **table;
public:
HashMap()
{
table = new HashEntry * [TABLE_SIZE];
for (int i = 0; i< TABLE_SIZE; i++)
{
table[i] = NULL;
}
}
/*
* Hash Function
*/
int HashFunc(int key)
{
return key % TABLE_SIZE;
}
/*
* Insert Element at a key
*/
void Insert(int key, int value)
{
int hash = HashFunc(key);
while (table[hash] != NULL && table[hash]->key != key)
{hash = HashFunc(hash + 1);
}
if (table[hash] != NULL)
delete table[hash];

table[hash] = new HashEntry(key, value);

/*

* Search Element at a key

*/

int Search(int key)

int hash = HashFunc(key);

while (table[hash] != NULL && table[hash]->key != key)

{
hash = HashFunc(hash + 1);

if (table[hash] == NULL)

return -1;

else

return table[hash]->value;

/*

* Remove Element at a key

*/

void Remove(int key)

int hash = HashFunc(key);

while (table[hash] != NULL)

if (table[hash]->key == key)

break;

hash = HashFunc(hash + 1);

if (table[hash] == NULL)

cout<<"No Element found at key "<<key<<endl;

return;

else

{
delete table[hash];

cout<<"Element Deleted"<<endl;

~HashMap()

for (int i = 0; i < TABLE_SIZE; i++)

if (table[i] != NULL)

delete table[i];

delete[] table;}

};

/*

* Main Contains Menu

*/

int main()

HashMap hash;

int key, value;

int choice;

hash.Insert(1, 10);

hash.Insert(2, 20);

hash.Insert(3, 30);

hash.Insert(4, 40);

if (hash.Search(2) == -1)
{

cout<<"No element found at key "<<key<<endl;

//continue;

/*

while (1)

cout<<"n----------------------"<<endl;

cout<<"Operations on Hash Table"<<endl;

cout<<"n----------------------"<<endl;

cout<<"1.Insert element into the table"<<endl;

cout<<"2.Search element from the key"<<endl;

cout<<"3.Delete element at a key"<<endl;

cout<<"4.Exit"<<endl;

cout<<"Enter your choice: ";

cin>>choice;

switch(choice)

case 1:

cout<<"Enter element to be inserted: ";

cin>>value;

cout<<"Enter key at which element to be inserted: ";

cin>>key;

hash.Insert(key, value);

break;

case 2:
cout<<"Enter key of the element to be searched: ";

cin>>key;

if (hash.Search(key) == -1)

cout<<"No element found at key "<<key<<endl;

continue;

}else

cout<<"Element at key "<<key<<" : ";

cout<<hash.Search(key)<<endl;

break;

case 3:

cout<<"Enter key of the element to be deleted: ";

cin>>key;

hash.Remove(key);

break;

case 4:

exit(1);

default:

cout<<"nEnter correct optionn";

*/

return 0;

}
2.

#include<iostream>

#include<cstdlib>

#include<string>

#include<cstdio>

using namespace std;

const int TABLE_SIZE = 128;

/*

* HashEntry Class Declaration

*/

class HashEntry

public:

int key;

int value;

HashEntry(int key, int value)

this->key = key;

this->value = value;

};

/*

* HashMap Class Declaration

*/

class HashMap

{
private:HashEntry **table;

public:

HashMap()

table = new HashEntry * [TABLE_SIZE];

for (int i = 0; i< TABLE_SIZE; i++)

table[i] = NULL;

~HashMap()

for (int i = 0; i < TABLE_SIZE; i++)

if (table[i] != NULL)

delete table[i];

delete[] table;

int HashFunc(int key);

void Insert(int key, int value);

int Search(int key);

void Remove(int key);

};

/*

* Hash Function
*/

int HashMap::HashFunc(int key)

return key % TABLE_SIZE;

/*

* * Insert Element at a key

*/

void HashMap::Insert(int key, int value)

int hash = HashFunc(key);

while (table[hash] != NULL && table[hash]->key != key)

hash = HashFunc(hash + 1);

if (table[hash] != NULL)

delete table[hash];

table[hash] = new HashEntry(key, value);

/*

* * Search Element at a key*/

int HashMap::Search(int key)

int hash = HashFunc(key);

while (table[hash] != NULL && table[hash]->key != key)

{
hash = HashFunc(hash + 1);

}
if (table[hash] == NULL)
return -1;
else
return table[hash]->value;
}
/*
* Remove Element at a key
*/
void HashMap::Remove(int key)
{
int hash = HashFunc(key);
while (table[hash] != NULL)
{
if (table[hash]->key == key)
break;
hash = HashFunc(hash + 1);
}
if (table[hash] == NULL)
{
cout<<"No Element found at key "<<key<<endl;
return;
}
else
{
delete table[hash];
}
cout<<"Element Deleted"<<endl;
}
/*
* Main Contains Menu
*/
int main()
{
HashMap hash;
int key, value;
int choice;
hash.Insert(1, 10);
hash.Insert(2, 20);
hash.Insert(3, 30);hash.Insert(4, 40);
if (hash.Search(2) == -1)
{
cout<<"No element found at key "<<key<<endl;
//continue;
}
/*
while (1)
{
cout<<"n----------------------"<<endl;
cout<<"Operations on Hash Table"<<endl;
cout<<"n----------------------"<<endl;
cout<<"1.Insert element into the table"<<endl;
cout<<"2.Search element from the key"<<endl;
cout<<"3.Delete element at a key"<<endl;
cout<<"4.Exit"<<endl;
cout<<"Enter your choice: ";
cin>>choice;
switch(choice)
{
case 1:
cout<<"Enter element to be inserted: ";
cin>>value;
cout<<"Enter key at which element to be inserted: ";
cin>>key;
hash.Insert(key, value);
break;
case 2:
cout<<"Enter key of the element to be searched: ";
cin>>key;
if (hash.Search(key) == -1)
{
cout<<"No element found at key "<<key<<endl;
continue;
}
else
{
cout<<"Element at key "<<key<<" : ";
cout<<hash.Search(key)<<endl;
}
break;
case 3:
cout<<"Enter key of the element to be deleted: ";
cin>>key;
hash.Remove(key);
break;
case 4:
exit(1);
default:
cout<<"nEnter correct optionn";
}}
*/
return 0;
}

Note:

1. Destructor cant be overloaded but constructor can be overloaded.

2. Yes, as C is the subset of C++, we can all the functions of C in C++ too.

2. Can I use ‘delete’ operator to release the memory which was allocated using malloc()

function of C language?

No, we need to use free() of C language for the same.


//Are there any special rules about inlining?

Yes, there are a few rules about inlining :

1. Any source files that used the inline function must contain the function’s definition.

2. An inline function must be defined everywhere. The easier way to deal with this to define
the function once in the class header file and include the definition as required. The harder
way is to redefine the function everywhere and learn the one-definition rule.

3. Main() can not be inline.

//Explain container class.

-Class to hold objects in memory or external storage. It acts as a generic holder.

- It has a predefined behaviour and a known interface.

- It is used to hide the topology used for maintaining the list of objects in memory.

- The container class can be of two types:

1. Heterogeneous container : Here the container class contains a group of mixed objects

2. Homogeneous container : Here the container contains all the same objects.

//Differentiate between late binding and early binding. What are the advantages of early
binding?

- Late binding refers to function calls that are not resolved until run time while early
binding refers to the events that occur at compile time.

- Late binding occurs through virtual functions while early binding takes place when all the
information needed to call a function is known at the time of compiling.
- Early binding increases the efficiency. Some of the examples of early binding are normal
function calls, overloaded function calls, and overloaded operators etc.

//When do you call copy constructors?

Copy constructors are called in these situations :

1. When compiler generates a temporary object.

2. When a function returns an object of that class by value .

3. When the object of that class is passed by value as an argument to a function .

4. When you construct an object based on another object of the same class.

//Name the implicit member functions of a class.

1. default constructor

2. copy constructor

3. assignment operator

4. default destructor

5. address operator

//Explain Stack unwinding.

Stack unwinding is a process during exception handling when the destructor is called for all
local objects between the place where the exception was thrown and where it is caught.

//How does code-bloating occur in C++?

- Improper use of Inline functions and templates may lead to code bloating.

- Multiple Inheritance may also lead to code bloating.


- Inline functions and templates, if not used properly, may lead to code bloating.

- Multiple Inheritance may also lead to code bloating (this is because the sub classes will
end up getting members from all the base classes even if only few members will suffice).

//Explain following storage classes in C++.

a. Auto :

- This is the default storage class.

- Variables in this class are automatically created and initialized when they are defined.

- These variable are then destroyed at the end of the block containing their definition.
They are not visible outside that block.

b. Register :

- This is a type of auto variable.

- It gives a suggestion to the compiler to use a CPU register for performance.

c. Static :

- A variable that is known only in the function that contains its definition.

- It is never destroyed and retains its value between calls to that function.

d. Extern :

- This is a static variable.

- Its definition and placement is determined when all object and library modules are
combined (linked) to form the executable code file.

- It can be visible outside the file where it is defined.


//What happens when you make call “delete this;”?

The two pit-falls exist here,

1. If it executes in a member function for an extern, static, or automatic object, the


program will probably crash as soon as the delete statement gets executed.

2. When an object finishes like this, the using program might not know about this end. As
far as the instantiating program is concerned, the object remains in scope and continues to
exist even though the object is finished. Subsequent dereferencing of the pointer can lead
to disaster.

//Explain deep copy and a shallow copy.

a. Deep copy :

It involves using the contents of one object to create another instance of the same class.
Here, the two objects may contain the same information but the target object will have its
own buffers and resources. The destruction of either object will not affect the remaining
objects.

b. Shallow copy :

It involves copying the contents of one object into another instance of the same class. This
creates a mirror image. The two objects share the same externally contained contents of
the other object to be unpredictable.This happens because of the straight copying of
references and pointers.

//What are the four partitions in which C++ compiler divides the RAM?

1. Stack Area :

This part of memory is used to store formal parameters, local variables, return addresses
of function call etc.

2. Program Code Area :

This part of memory is used to store the object code of the program.
3. Global Variable Section :

This part of memory is used to store global variables defined in the program.

4. Heap Area or Free Storage Pool :

It consists of unallocated memory locations which are allocated dynamically during program
execution using new operator.

//What are the various situations where a copy constructor is invoked?

Various situations where a copy constructor is invoked are as follows :

- When an object is defined and initializes with the values of another object of the same
type, then copy constructor is invoked.

- When an object is passed by value method, then copy constructor is invoked to create the
copy of the passed object for the function.

- When a function returns an object, then copy constructor is invoked to create a


temporary object to hold the return value in the memory.

//vtable

//smart pointer

//object slicing

//zombie objects
//set new handler

//typecasting

1. static_cast

2. dynamic_cast

3. const_cast

4. reinterpret_cast

//this pointer

//reference pointer

//What is the difference between a deep copy and a shallow copy?

Deep copy involves using the contents of one object to create another instance of the same
class. In a deep copy, the two objects may contain ht same information but the target
object will have its own buffers and resources. the destruction of either object will not
affect the remaining object. The overloaded assignment operator would create a deep copy
of objects.

Shallow copy involves copying the contents of one object into another instance of the same
class thus creating a mirror image. Owing to straight copying of references and pointers,
the two objects will share the same externally contained contents of the other object to be
unpredictable.

Using a copy constructor we simply copy the data values member by member. This method
of copying is called shallow copy. If the object is a simple class, comprised of built in types
and no pointers this would be acceptable. This function would use the values and the objects
and its behavior would not be altered with a shallow copy, only the addresses of pointers
that are members are copied and not the value the address is pointing to. The data values of
the object would then be inadvertently altered by the function. When the function goes out
of scope, the copy of the object with all its data is popped off the stack. If the object has
any pointers a deep copy needs to be executed. With the deep copy of an object, memory is
allocated for the object in free store and the elements pointed to are copied. A deep copy
is used for objects that are returned from a function.

// Vector vs Lists

Lists:

Each item contains an address to the next or previous element, so with this feature, you can
randomize the items, even if they aren't sorted, the order won't change: it's efficient if
you memory is fragmented. But it also has an other very big advantage: you can easily
insert/remove items, because the only thing you need to do is change some pointers.
Drawback: To read a random single item, you have to jump from one item to another until
you find the correct address.

Vectors:

When using vectors, the memory is much more organized like regular arrays: each n-th
items is stored just after (n-1)th item and before (n+1)th item. Why is it better than list ?
Because it allow fast random access. Here is how: if you know the size of an item in a vector,
and if they are contiguous in memory, you can easily predict where the n-th item is; you
don't have to browse all the item of a list to read the one you want, with vector, you
directly read it, with a list you can't. On the other hand, modify the vector array or change
a value is much more slow.

Lists are more appropriate to keep track of objects which can be added/removed in
memory. Vectors are more appropriate when you want to access an element from a big
quantity of single items.

I don't know how lists are optimized, but you have to know that if you want fast read
access, you should use vectors, because how good the STL fasten lists, it won't be as fast in
read-access than vector.

vector:

- Contiguous memory.

- Pre-allocates space for future elements, so extra space required beyond what's
necessary for the elements themselves.
- Each element only requires the space for the element type itself (no extra pointers).

- Can re-allocate memory for the entire vector any time that you add an element.

- Insertions at the end are constant, amortized time, but insertions elsewhere are a
costly O(n).

- Erasures at the end of the vector are constant time, but for the rest it's O(n).

- You can randomly access its elements.

- Iterators are invalidated if you add or remove elements to or from the vector.

- You can easily get at the underlying array if you need an array of the elements.

list:

- Non-contiguous memory.

- No pre-allocated memory. The memory overhead for the list itself is constant.

- Each element requires extra space for the node which holds the element, including
pointers to the next and previous elements in the list.

- Never has to re-allocate memory for the whole list just because you add an element.

- Insertions and erasures are cheap no matter where in the list they occur.

- It's cheap to combine lists with splicing.

- You cannot randomly access elements, so getting at a particular element in the list can
be expensive.

- Iterators remain valid even when you add or remove elements from the list.

- If you need an array of the elements, you'll have to create a new one and add them all
to it, since there is no underlying array.
// Why virtual constructor not possible?

Virtual functions are used in order to invoke functions based on the type of object pointed
to by the pointer, and not the type of pointer itself. But a constructor is not "invoked". It is
called only once when an object is declared. So, a constructor cannot be madevirtual in C++.

//Singleton pattern Applicability & Examples

According to the definition the singleton pattern should be used when there must be
exactly one instance of a class, and when it must be accessible to clients from a global
access point. Here are some real situations where the singleton is used:

Example 1 - Logger Classes

The Singleton pattern is used in the design of logger classes. This classes are ussualy
implemented as a singletons, and provides a global logging access point in all the application
components without being necessary to create an object each time a logging operations is
performed.

Example 2 - Configuration Classes

The Singleton pattern is used to design the classes which provides the configuration
settings for an application. By implementing configuration classes as Singleton not only that
we provide a global access point, but we also keep the instance we use as a cache object.
When the class is instantiated( or when a value is read ) the singleton will keep the values in
its internal structure. If the values are read from the database or from files this avoids
the reloading the values each time the configuration parameters are used.

Example 3 - Accesing resources in shared mode

It can be used in the design of an application that needs to work with the serial port. Let's
say that there are many classes in the application, working in an multi-threading
environment, which needs to operate actions on the serial port. In this case a singleton with
synchronized methods could be used to be used to manage all the operations on the serial
port.

Example 4 - Factories implemented as Singletons

Let's assume that we design an application with a factory to generate new objects(Acount,
Customer, Site, Address objects) with their ids, in an multithreading environment. If the
factory is instantiated twice in 2 different threads then is possible to have 2 overlapping
ids for 2 different objects. If we implement the Factory as a singleton we avoid this
problem. Combining Abstract Factory or Factory Method and Singleton design patterns is a
common practice.

You might also like