CPP
CPP
1.1 cin.
1.2 cout.
2. Classes.
3. More on Classes.
3.3 Namespaces.
4.2 Assignment
4.3 Constructors
4.4 Destructors
5. Inheritance.
6. Polymorphism.
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. 8 Namemangling
12. IO Streams
New : new() = malloc() + constructor()
3. More on Classes.
3.3 Namespace.
#include <iostream>
class Line
public:
return *this;
};
~Line(); // destructor
private:
int *ptr;
};
Line::Line(int len)
*ptr = len;
// {
// return *this;
// }
Line::~Line(void)
delete ptr;
return *ptr;
int main( )
//display(line1);
//display(line2);
return 0;
eg2:
#include<iostream>
#include<cstring>
class String
private:
char *s;
int size;
public:
};
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
delete [] s;
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
size = old_str.size;
s = new char[size+1];
strcpy(s, old_str.s);
int main()
String str1("GeeksQuiz");
str2.print();
str2.change("GeeksforGeeks");
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++
#include <iostream>
class myclass {
int a;
public:
myclass(int x) { a = x; }
};
int main()
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
class myclass
int a;
public:
explicit myclass(int x)
a = x;
};
myclass ob(4);
will be invalid
4.2 Destructor
4.4 Assignment
7. Exception Handling
Standard library exceptions:
8. RTTI
8.1 typeid(obj)
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) ;
#include <typeinfo>
int main()
int i, j;
float f;
char *p;
myclass1 ob1;
myclass2 ob2;
if(typeid(i) == typeid(j))
if(typeid(i) != typeid(f))
if(typeid(ob1) != typeid(ob2))
return 0;
1. const_cast
const_cast(expression) The const_cast<>() is used to add/remove
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
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
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
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;
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
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++
Eg:
# include <iostream>
# include <cstdlib>
# include <new>
int cnt = 0;
void my_handler()
exit(1);
int main()
set_new_handler(my_handler);
while(1)
cnt++;
return 0;
}
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
Container classes:
Sequences:
Associative Containers:
structure.
Container adapters:
stack LIFO
queue FIFO
String:
manipulating bits.
Operations/Utilities:
container classes
leaks.
File IO Streams
https://www.codingunit.com/cplusplus-tutorial-file-io-in-cplusplus-text-and-
binary-files
In the tables below we will see the various steps and operations that can be performed
to use files in C++
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
#include <fstream>
int main()
ofstream SaveFile("cpp-home.txt");
SaveFile.close();
return 0;
#include <fstream.h>
ifstream OpenFile("cpp-home.txt");
char ch;
while(!OpenFile.eof())
OpenFile.get(ch);
OpenFile.close();
#include <fstream.h>
void main()
SaveFile.close();
eg 4:
#include <fstream.h>
void main()
File.close();
#include <fstream.h>
void main()
{
char ch;
ch='o';
File.close();
#include <fstream.h>
#include <string.h>
void main()
char arr[13];
static char read_array[10]; //I will put the read data, here
File.close();
#include <fstream.h>
void main()
{
ifstream File("test_file.txt");
char arr[10];
File.read(arr,10);
File.close();
eg 9: Getline
#include <fstream.h>
void main()
ifstream File("test_file.txt");
*/
File.getline(arr,10,'o');
File.close();
eg 10:
#include <fstream.h>
void main()
{
ifstream File("test_file.txt");
char ch;
File.get(ch);
File.get(ch);
File.close();
eg 11:
void main()
ofstream File;
File.close();
File.open("delete_test.txt",ios::nocreate);
//see if it returned it
if(File.rdstate() == ios::failbit)
File.close();
}
eg 12:
#include <fstream.h>
void main()
ifstream File("test_file.txt");
char ch;
File.get(ch);
File.putback(ch);
File.get(ch);
File.close();
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.
asm ("op-code");
where op-code is the assembly language instruction that will be embedded in your program.
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
#include <iostream>
int main()
return 0;
Types of errors
1. Syntax error:-
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
int num = 0;
int avg;
Floating exception
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).
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 refers to, providing only essential information to the outside world
and hiding their background details, i.e., to represent the needed information in program
Any C++ program where you implement a class with public and private members is an example
#include <iostream>
class Adder
public:
//Constructor
Adder(int i = 0)
total = i;
total += num;
int getTotal()
return total;
}
private:
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
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.
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
4. Classes inheriting an Abstract Class must implement all pure virtual functions, or
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
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.
#include<iostream>
class A
public:
int i;
};
public:
int j;
};
public:
int k;
};
public:
int sum;
};
int main()
D ob;
ob.j = 20;
ob.k = 30;
cout << “Value of j is : ”<< ob.j<<”\n”; cout << “Value of k is :”<< ob.k<<”\n”;
return 0;
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.
The singleton design pattern is used whenever the design requires only one instance of a
singleton class)
Logger classes. For logging purposes of an application there is usually one logger
instance required.
Singleton
Singleton example:
#include <iostream>
using namespace std;
// Singleton class
class MySingleton {
public:
public:
private:
// private constructor
MySingleton();
};
MySingleton::MySingleton()
MySingleton* MySingleton::GetInstance()
{
if ( iInstance == NULL )
return iInstance;
void main()
MySingleton* obj;
obj = MySingleton::GetInstance();
OUTPUT:
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
thread-safe access to the object's global state.Prevents the global namespace from being
polluting.
Singleton example 2:
#include <iostream>
class Singleton
public:
private:
Singleton(){}
};
Singleton* Singleton::instance = 0;
Singleton* Singleton::getInstance()
if(!instance)
return instance;
else
return instance;
int main()
return 0;
constructor would not return a value, there is no confirmation that whether the constructor
An object that is freed does not crash the applications. The application debugging is
Encapsulation Vs Abstraction
Encapsulation:--Information hiding.
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:
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
Objects in existence: 1
Objects in existence: 2
Objects in existence: 3
Objects in existence: 2
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
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
#include <iostream>
using namespace std;
class static_type
{
static int i;
public:
static void init(int x) {i = x;}
void show() {cout << i;}
};
int main()
static_type x;
x.show(); // displays 100
return 0;
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.
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;
int main()
return 0;
ob.set_i(2);
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
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
A function may return an object to the caller. For example, this is a valid C++ program:
class myclass
{
int i;
public:
void set_i(int n) { i=n; }
int get_i() { return i; }
};
myclass f();
int main()
myclass o;
o = f();
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
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()
ob1.set_i(99);
ob2 = ob1; // assign data from ob1 to ob2
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
#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;
ob[i].set_i(i+1);
return 0;
#include <iostream>
using namespace std;
class cl
{
int i;
public:
cl(int j) { i=j; } // constructor
int get_i() { return i; }
};
int main()
int i;
return 0;
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;
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()
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
return 0;
You may assign one pointer to another only if the two pointer types are compatible. For
example, given:
int *pi;
float *pf;
Of course, you can override any type incompatibilities using a cast, but doing so bypasses C+
#include <iostream>
using namespace std;
class base
{
int i;
public:
void set_i(int num) { i=num; }
int get_i() { return i; }
};
public:
void set_j(int num) { j=num; }
int get_j() { return j; }
};
int main()
base *bp;
derived d;
/* 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:
((derived *)bp)->set_j(88);
The type of pointer that "points" generically to a member of a class, not to a specific
#include <iostream>
using namespace std;
class cl
{
public:
cl(int i) { val=i; }
int val;
int double_val() { return val+val; }
};
int main()
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()
return 0;
References
as a function parameter.
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
#include <iostream>
using namespace std;
int main()
{
int x;
x = 10;
cout << x << " negated is ";
neg(&x);
cout << x << "\n";
return 0;
*i = -*i;
int main()
int x;
x = 10;
cout << x << " negated is ";
return 0;
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)
{
id = num;
cl::~cl()
{
cout << "Destructing " << id << "\n";
int main()
cl o(1);
o.i = 10;
o.neg(o);
return 0;
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;
int main()
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
the element of s that is specified by its argument i. The reference returned by replace( )
Bitwise copy means copy an whole object directly. Where it will be used? I don't know,
to achieve it.
class MyClass {
int *p;
public:
};
int main()
MyClass obj1,obj2;
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
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
MainObject2.
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
reflect in MainObject2.
A a;
// 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()
{
2. The clients of the class know what member functions the class provides, how to call them
3. The clients do not know how the class's member functions are implemented.
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
To get the value pointed to by a pointer, you need to use the dereferencing operator * (e.g.,
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
pointers.
2) References cannot be NULL. Pointers are often made NULL to indicate that they are not
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
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
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 ++.
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.
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.
1. Virtual Table is a lookup table of function pointers used to dynamically bind the virtual
3. Every class that uses virtual functions (or is derived from a class that uses virtual
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
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
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;
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
#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
'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
4.Inline functions are kept in the Symbol Table by the compiler, and all the call for such
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.
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.
Advantages :-
2. It also save overhead of variables push/pop on the stack, while function calling.
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
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:
functions).
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
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 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
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
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
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
•Determine that the desired page is already in RAM (but not allocated to the
•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
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:
•The page is faulted back into memory(most likely forcing some other processes' pages to
be swapped out)
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;
}
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
Which of the following two statements call copy constructor and which one calls assignment
operator?
MyClass t1=t2;
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
more details
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
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,
algorithms & co. Anyhow, for the very limitation of fixed size it's much less flexible than
std::vector .
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
1. the compiler will generate a default constructor for you unless you declare any
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
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
// 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).
•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
•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.
•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
• 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
• A process is sometimes referred as active entity as it resides on the primary memory and
Switchframe) is a data structure in the operating system kernel containing the information
3. Scheduling information
4. Memory-management information
5. Accounting information
• The current state of the process i.e., whether it is ready, running, waiting, or whatever.
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.
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.
orphan process
system any orphaned process will be immediately adopted by the special init
interactive user. Zombies hardly take any memory. Orphans are regular
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
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
space into the physical memory of the machine. Allows more number of
process size than the available physical memory. Demand paging systems
3.TCP gurantees that as long as you have a connection data sent will arrive at
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
inode is
File type
File permissions
Link count
User ID number of the file owner and the group ID number of the
associated group
Section Numbers
The section numbers of the manual are listed below. While reading
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
6 Games
Link are of two types Soft links (symbolic links ) or Hard link
◦ You can make links for files & folder & you can create link (shortcut) on
different
2.Hard Links
◦ For files only & you cannot create on different partition ( it should be on
same partition )
◦ If the real copy is deleted the link will work ( because it act as original file
• Soft links are very similar to what we say “Shortcut” in windows, is a way
In more technical words, in soft link, a new file is created with a new inode,
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
$ ln -s /usr/bin/gedit ~/Desktop/gedit
• 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
# ln
# ln /usr/bin/gedit ~/Desktop/gedit
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
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
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
•Original File and Hard Linked file contain different inode values
•Any changes to either original file or soft linked file are reflected in the other file
•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
• 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
1. lscpu
The lscpu command reports information about the cpu and processing units. It does
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.
Hwinfo is another general purpose hardware probing utility that can report detailed
and brief information about multiple different hardware components, and more than
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
Lists out the scsi/sata devices like hard drives and optical drives.
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
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
List out information all block devices, which are the hard drive partitions and other
Reports various partitions, their mount points and the used and available space on
each.
better than df
11. fdisk
Fdisk is a utility to modify partitions on hard drives, and can be used to list out the
12. mount
Check the amount of used, free and total amount of RAM on system with the free
command.
14. dmidecode
hardware information byreading data from the SMBOIS data structures (also called DMI
tables).
Many of the virtual files in the /proc directory contain information about hardware
and configurations.
# cpu information
$ cat /proc/cpuinfo
# memory information
$ cat /proc/meminfo
$ cat /proc/version
16. hdparm
The hdparm command gets information about sata devices like hard disks.
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 in objects
1347861486 = 80.86.187.238
Simple Makefile
CC = g++
CFLAGS = -O
simplecpp: ${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() 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
## 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 =====
Clone(): creates a new thread within a processint clone(int (*fn)(void *), void *child_stack,
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
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
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
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
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
Transport Header
Data
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
Network Header
Transport Header
Data
102.231.4.189
102.231.4.189
102.231.4.189
102.231.4.189
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
Network Header
Transport Header
Data11-22-33-44-55
102.231.4.189
11-22-33-44-55
102.231.4.189
11-22-33-44-55
102.231.4.189
11-22-33-44-55
102.231.4.189
These four packets can then be sent across the internet holding enough
1.reach their destination (socket from the Network and Transport Layers)
2.find the correct network interface (MAC address from the Link Layer)
Transport Layer)
Answer :
Socket
What is the MAC Address for in the TCP/IP stack?
• Answer :
Application
"Hello"
Transport
:80
1/1
"Hello"
Internet
To=98.125.43.88
From=12.32.72.2
:80
1/1
"Hello"
Link
To MAC = A0.3D.EF.00
To=98.125.43.88
From=12.32.72.2
:80
1/1
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];
/*
*/
{
hash = HashFunc(hash + 1);
if (table[hash] == NULL)
return -1;
else
return table[hash]->value;
/*
*/
if (table[hash]->key == key)
break;
if (table[hash] == NULL)
return;
else
{
delete table[hash];
cout<<"Element Deleted"<<endl;
~HashMap()
if (table[i] != NULL)
delete table[i];
delete[] table;}
};
/*
*/
int main()
HashMap hash;
int choice;
hash.Insert(1, 10);
hash.Insert(2, 20);
hash.Insert(3, 30);
hash.Insert(4, 40);
if (hash.Search(2) == -1)
{
//continue;
/*
while (1)
cout<<"n----------------------"<<endl;
cout<<"n----------------------"<<endl;
cout<<"4.Exit"<<endl;
cin>>choice;
switch(choice)
case 1:
cin>>value;
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)
continue;
}else
cout<<hash.Search(key)<<endl;
break;
case 3:
cin>>key;
hash.Remove(key);
break;
case 4:
exit(1);
default:
*/
return 0;
}
2.
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstdio>
/*
*/
class HashEntry
public:
int key;
int value;
this->key = key;
this->value = value;
};
/*
*/
class HashMap
{
private:HashEntry **table;
public:
HashMap()
table[i] = NULL;
~HashMap()
if (table[i] != NULL)
delete table[i];
delete[] table;
};
/*
* Hash Function
*/
/*
*/
if (table[hash] != NULL)
delete table[hash];
/*
{
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:
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?
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.
- It is used to hide the topology used for maintaining the list of objects in memory.
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.
4. When you construct an object based on another object of the same class.
1. default constructor
2. copy constructor
3. assignment operator
4. default destructor
5. address operator
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.
- Improper use of Inline functions and templates 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).
a. Auto :
- 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 :
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 :
- Its definition and placement is determined when all object and library modules are
combined (linked) to form the executable code file.
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.
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.
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.
It consists of unallocated memory locations which are allocated dynamically during program
execution using new operator.
- 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.
//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
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).
- 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.
- 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++.
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:
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.
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.
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.
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.