The following C++ and Database questions asked on during my C++ job interviews. I hope these questions may helpful to you.
Why copy constructor is needed?
Copy constructor is needed when the class have any pointers of data. or any data members of class are pointers.
When is data members of class is allocated memory using dynamic memory allocation of new operator, then in order to create another object from existing object, it is mandate to use the user defined copy constructor.
What kind of copy does by copy constructor?
It does the deep copy.
What is the difference between shallow copy and deep copy?
Shallow copy is nothing but the assignment operator (a=b), it just copy the value of the variable to another, but it doesn't worry about the references.
object1= object2
Deep copy comes in to picture only when there are any pointers in the class and to create any new object from the existing object, we need to copy the object references (address) to create the exact copy of object from existing object.
class_name new_object= old_objectcopy constructor performs the deep copy.
How does the copy constructor signature looks like?
Class_name (const class_name &old_object)
class_name (volatile class_name &old_object)
class_name (class_name &old_object)
class_name (class_name &old_object, double = 1.0, int = 42)
class_name (class_name &old_object, double = 1.0)
class_name (volatile const class_name &old_object)
When does copy constructor is been called?
Base_class new_object= old_object
Base_class new_object(old_object)
new_object(old_object)
When an object is returned by value as below:
Base_class new_object= function(old_object)
What is implicit copy constructor and user define (explicit) copy constructor?
Default copy constructor or Implicit copy constructor. Implicit copy constructor also called as default copy constructor. The compiler will generate the default copy constructor.
If the programmer did not declared the copy constructor for a class, the compiler will add its own default copy constructor for the objects derived from that class.
Default copy constructor does a very simple operation, they will do a bit-wise (member-wise) copy of an object, which means that the object will be copied bit by bit.
#include<iostream>
#include<string>
using namespace std;
class Base
{
private:
int EmpId;
int age;
public:
Base(int a, int b);
};
Base :: Base(int a, int b)
{
EmpId =a;
age=b;
}
int main()
{
Base obj1(2, 20);
Base obj2=obj1; // Compiler creates Default Copy constructor
}
How Default or copy constructor Looks like?
Base::Base(const Base &Otherobject): EmpId (Otherobject.EmpId ), age (Otherobject.age)
{
}
Example #1
#include<iostream>
#include<string>
using namespace std;
class Base
{
private:
int EmpId;
int age;
public:
Base(int a, int b);
// Copy constructor
Base(const Base &otherObj);
void display();
};
Base :: Base(int a, int b)
{
cout<<" I am in the constructor"<<endl;
EmpId =a;
age=b;
}
// Default Copy constructor which does bit by bit copy (Shallow Copy)
// When there is Pointer variable it will lead to crash.
Base :: Base(const Base &otherObj)
{
cout<<" I am in the Copy constructor"<<endl;
EmpId =otherObj.EmpId;
age=otherObj.age;
}
void Base :: display()
{
cout<<"The EMPID and Age" <<"\t"<<EmpId<<"\t"<<age<<endl;
}
int main()
{
Base obj1(2, 20);
// Copy constructor
Base obj2=obj1;
obj2.display();
}
What happens if there is a pointer member variable in class?
There is a danger in copying an object bit by bit, if the object contains pointers since the pointer address will be copied in the process resulting in two different objects that share the same memory buffer.
You can imagine what will happen when two copies of an object calls their destructors one after the other. The first object that call its destructor will have no problems, since it will try to deallocate the pointer and succeed, but the second objects destructor try to de allocate a pointer which does not exist anymore and the whole application crashes!
Why you need user define (explicit) copy constructor?
If the object have pointers, then there is a need to have explicit or user defined copy constructor for deep copy.
Example #2
New and Malloc is used for allocating memory dynamically ( during run time)
Source: http://stackoverflow.com/questions/240212/what-is-the-difference-between-new-delete-and-malloc-free
new:
The first expression is used to allocate memory to contain one single element of type
The second one is used to allocate a block (an array) of elements of type
int *p = new int; // allocates 1 Uninitialized int
int *q = new int[4]; // allocates 4 Uninitialized int's
int *p = new int(); // allocates 1 int and initialized to Zero
int *q = new int[4](); // allocates 4 int's and initialized to Zero's
In the above example, the first expression is used to allocate memory to contain one single element of type
the system dynamically allocates space for four elements of type
delete:
delete pointer;
delete[] pointer;
The first statement releases the memory of a single element allocated using new.
Second one releases the memory allocated for arrays of elements using new and a size in brackets ([])
delete p;
delete [] q;
As mentioned above, new never returns NULL, it throws an exception as bad_alloc and it should be handled using catch(std::bad_alloc&)
Specify a special object called nothrow, declared in header <new>, as argument for new:
int *s;
s = new (nothrow) int [5]; In this case, if the allocation of this block of memory fails, the failure can be detected by checking if s is a null pointer:
int * s;
s = new (nothrow) int [5];
if (s == nullptr) { // There is no NULL, validate with nullptr
// error assigning memory. Take measures.
}
In the new compilers, there is no need to check pointer for null.
or Simply write using the smart pointers.
Example #1:
class Base {
public:
Base (int c, int r);
// no default constructor
// ...
};
class Y {
public:
Y(); // default constructor
// ...
};
void func(int n)
{
void* p1 = malloc(40); // allocate 40 (uninitialized) bytes
int* p2 = new int[10]; // allocate 10 uninitialized ints
int* p3 = new int(10); // allocate 1 int initialized to 10
int* p4 = new int(); // allocate 1 int initialized to 0
int* p4 = new int; // allocate 1 uninitialized int
Base * pc1 = new Circle(10,10); // allocate a Circle constructed
// with the specified argument
Base * pc2 = new Base; // error no default constructor
Y* px1 = new Y; // allocate a default constructed Y
Y* px2 = new Y(); // allocate a default constructed Y
Y* px2 = new Y[10]; // allocate 10 default constructed Y
// ...
}
Example #2:
#include<iostream>
using namespace std;
class base
{
public:
base(){ cout<<"Constructor is called"<<endl;}
~base() { cout<<"destructor is called"<<endl;}
};
int main()
{
int *q= new int; // allocate 1 int which is uninitialized
int *p= new int(10); // allocate 1 int which is initialized to 10
base *b = new base(); // Constructor is called
base *obj= new base[2]; // Two objects created and two times the constructor is called.
cout<<" The value of q is"<<endl<<*q<<endl;
cout<<" The value of p is"<<endl<<*p<<endl;
delete b; // Destructor is called
delete [] obj; // 2 times destructor is called.
delete q; // Frees the memory
delete p; // Frees the memory
return 0;
}
Some more tips:
What happens when class objects created:
Case 1:
Derived1 d1;
d1-> vptr points to the virtual Table of Derived1 class.
Case 2:
Derived1 d1;
Base *bp;
bp=&d1;
Even tough the bp is base pointer, it is pointing to address of derived class object through
which it access the virtual table of Derived1 class.
bp->vptr points to the virtual Table of Derived1 class.
Example Program #1:
#include<iostream>
using namespace std;
class Bank
{
public:
virtual void interestRate()
{
cout<< "BASE Interest Rate is Zero"<<endl;
}
};
class stateBank : public Bank
{
public:
//Derived the functionality of BANK class
virtual void interestRate() // or void interestRate()
{
cout<< "STATE BANK INTEREST RATE: 9.5%"<<endl;
}
};
class indianBank : public Bank
{
public:
// Derived the functionality of BANK class
virtual void interestRate() // or void interestRate()
{
cout<< "INDIAM BANK INTEREST RATE: 10.5%"<<endl;
}
};
int main()
{
Bank *bp, bObj;
stateBank st;
indianBank indObj;
// Upcasting
bp= &st; // Upcasting
bp->interestRate();
bp= &indObj; // Upcasting
bp->interestRate();
bp=&bObj;
bp->interestRate();
st.interestRate();
indObj.interestRate();
return 0;
}
Output:
STATE BANK INTEREST RATE: 9.5%
INDIAM BANK INTEREST RATE: 10.5%
BASE Interest Rate is Zero
STATE BANK INTEREST RATE: 9.5%
INDIAM BANK INTEREST RATE: 10.5%
Example Program #2:
#include<iostream>
using namespace std;
class Fruit
{
public:
virtual void color()
{
cout<< "color is based on Type Fruit "<<endl;
}
virtual void taste()
{
cout<< "Taste is based on Type Fruit "<<endl;
}
};
class Apple : public Fruit
{
public:
//Derived the functionality of BANK class
virtual void color()
{
cout<< "Apple color is RED"<<endl;
}
};
class Mango : public Fruit
{
public:
virtual void taste()
{
cout<< "Mango Taste is Yummy"<<endl;
}
};
int main()
{
Fruit *fp;
Apple ap;
Mango mang;
// Upcasting
fp= ≈ // Upcasting
fp->color();
fp->taste();
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
};
int main()
{
Derived d;
return 0;
}
Output:
Inheritance Example 2# With Derived class constructor having Parameters
Base class constructors are automatically called for you if they have no argument.
If you want to call a Base class constructor with an argument, you must use the subclass's (derived) constructor initialization list.
Inheritance Example 4# Specify which Base constructor to be called.
#include<iostream>
using namespace std;
class Base
{
int a;
public:
Base() // This will not be called.
{
cout<<"Default Constructor is called\n";
}
Base(int j)
{
a=j;
cout<<"Base Constructor is called\t"<<a<<endl;
}
};
class Derived: public Base
{
int b;
public:
Derived(int j): Base(j)
{
b=j;
cout<<"Derived Constructor with one parameter is called\t"<<b<<endl;
}
};
int main()
{
Derived d2(2);
return 0;
}
Output:
Base Constructor is called 2
Derived Constructor with one parameter is called 2
Inheritance Example 5#
#include<iostream>
using namespace std;
class Base
{
int a;
public:
Base(int j)
{
a=j;
cout<<"Base Constructor is called\t"<<a<<endl;
}
};
class Derived: public Base
{
int b;
public:
Derived(int j1, int j2): Base(j1)
{
b=j2;
cout<<"Derived Constructor with one parameter is called\t"<<b<<endl;
}
};
Derived class is dependent on Base class.So first compiler intialise the Base class members and then intialise the derived class.
Rule # 2 : Order of Destructor Call
A Base class constructor will always be called before the derived constructor.
Whereas, in case of order of destructor calls it is exactly opposite,
the Base class destructor will be called after Derived class destructor.
Derived class destructor called first and then Base class constructor is called.
Example 1# -> Simple example of order of destructor
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base class Constructor is called\n";
}
~Base()
{
cout<<"Base class destructor Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Derived d1;
return 0;
}
Output:
Base class Constructor is called
Derived Constructor is called
Derived class destructor is called
Base class destructor is called
Example 1# -> with delete Operator
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base class Constructor is called\n";
}
~Base()
{
cout<<"Base class destructor Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Derived *d1 = new Derived();
delete d1;
return 0;
}
Output:
Base class Constructor is called
Derived Constructor is called
Derived class destructor is called
Base class destructor is called
Let's see the below example: >>>>>>>> Why you need virtual destructor
Example 1# -> with Base class pointer having derived class object address
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base class Constructor is called\n";
}
~Base()
{
cout<<"Base class destructor Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
Base class Constructor is called
Derived Constructor is called
Base class destructor is called
>>> derived class destructor never be called, it is memory leak. Then what is the solution.. Solution is only use the Virtual destructor.
using namespace std;
class Base
{
public:
~Base()
{
cout<<"Base class destructor is called\n";
}
};
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived(); // Upcasting
delete d1;
return 0;
}
How to overcome this kind of issue? Use of Virtual destructor
When ever there is a UPCASTING or Base class pointer assigned with the derived class object address. Then , we should use "Virtual" destructor in the base class to avoid the memory leaks.
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base()
{
cout<<"Base class destructor is called\n";
}
};
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
Base::~Base() // Mandatory
{
cout<<"Base class destructor is called\n";
}
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
Let's create object for the Base class. Abstract class can't create objects.
Static_cast:
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
// This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base),
// in the same way as allowed as an implicit conversion.
//Up Casting
b= &d1;
// Upcasting
d= new Derived;
b= d;
return 0;
}
Output #
As in the above example, it does the implicit conversion of up casting.
Example#2 : Down Casting (converting from pointer-to-base to pointer-to-derived) -> It is not safe and it may yield to NULL ptr or Undefined behavior.
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
//Down Casting
d= &ob;
// Down casting
b= new Base;
d= b;
return 0;
}
Output #
In function ‘int main()’:
error: invalid conversion from ‘Base*’ to ‘Derived*’ [-fpermissive]
d= &ob;
^
error: invalid conversion from ‘Base*’ to ‘Derived*’ [-fpermissive]
d= b;
^
-> Then Solution is : Use Static Cast to avoid these errors
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
//Down Casting
d= static_cast<Derived *>(&ob);
// Down casting
b= new Base;
d= static_cast<Derived *>(b);
return 0;
}
Output:
Here if you observe, static_cast doesn't return any value, it is up to the programmer to keep safe.
dynamic_cast :
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
//Down Casting
d= dynamic_cast<Derived *>(&ob);
// Down casting
b= new Base;
d= dynamic_cast<Derived *>(b);
return 0;
}
Output:
Compilation Errors: Since the class is not polymorphic.
In function ‘int main()’:
error: cannot dynamic_cast ‘& ob’ (of type ‘class Base*’) to type ‘class Derived*’ (source type is not polymorphic)
d= dynamic_cast<Derived *>(&ob);
^
error: cannot dynamic_cast ‘b’ (of type ‘class Base*’) to type ‘class Derived*’ (source type is not polymorphic)
d= dynamic_cast<Derived *>(b);
^
Example #2 : DownCasting for a polymorphic class (with virtual function in class)
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(){}
};
class Derived: public Base
{
int a;
public:
void fun(){}
};
int main()
{
Base *b, ob;
Derived *d, d1;
// Down casting
d= dynamic_cast<Derived *>(&ob);
// Down casting
b= new Base();
d= dynamic_cast<Derived *>(b);
if(d == NULL)
{
cout<< "NULL"<<endl;
}
return 0;
}
Output:
dynamic_cast.cpp: In function ‘int main()’:
dynamic_cast.cpp:22:33: warning: dynamic_cast of ‘Base ob’ to ‘class Derived*’ can never succeed [enabled by default]
d= dynamic_cast<Derived *>(&ob);
Reason for the compiler warning:
'Base' class don't have any Derived class part. so it cannot be casted.
When you create Base object, it will not have anything which Derived contains and hence when you cast it to derived, the Derived's part will not be there. Also, polymorphism will work with pointers and references.
The compiler will not stop you from doing anything stupid things. It will just warn you
Example #3 : Up casting and Down casting using Dynamic Cast.
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(){}
};
class Derived: public Base
{
};
int main()
{
Base *b, *ob;
Derived *d, *d1;
//Upcasting
d1= new Derived();
ob=dynamic_cast<Base *>(d1);
if(ob == NULL)
cout<< "NULL"<<endl;
else
cout<< "NOT NULL"<<endl;
// Down casting
b= new Base();
d= dynamic_cast<Derived *>(b);
if(d == NULL)
{
cout<< "NULL"<<endl;
}
return 0;
}
Output:
NOT NULL
NULL
Here the dynamic cast operator returns the valid pointer if it is converted properly else it will return zero.The down casting always fail and return the NULL pointer.
const_cast
#include <iostream>
using namespace std;
void print (int *ctr)
{
cout << *ctr << '\n';
}
int main () {
const int val = 10;
const int *ptr = &val;
print ( const_cast<int *> (ptr) );
return 0;
}Output:
10
Notes : It converts the constant pointer to non constant pointer.
Example #2 : convert the const type to non const using const_cast.
#include <iostream>
using namespace std;
void print (char *ctr)
{
cout << ctr << '\n';
}
int main () {
const char *ptr = "muni";
print ( const_cast<char *> (ptr) );
return 0;
}
Output:
Muni
reinterpret_cast
#Example 1: If there are two different classes, then try to convert one class pointer type to another class pointer type by using static_cast leads to error.
#include<iostream>
using namespace std;
class X
{
};
class Y
{
};
int main()
{
X *ox;
Y *oy;
ox= new X;
oy= static_cast<Y *>(ox);
return 0;
}
# compile Error: X and Y are unrelated classes and you can't use the static_cast for unrelated classes and it is strictly to be used for related classes.
Example #2 : Convert one pointer type of class to another pointer of class type (But it is not safe).
#include<iostream>
using namespace std;
class X
{
};
class Y
{
};
int main()
{
X *ox;
Y *oy;
ox= new X;
oy= reinterpret_cast<Y *>(ox);
return 0;
}
#Notes:
This code compiles, although it does not make much sense, since oy points to an object of a totally unrelated and likely incompatible class. Dereferencing b is unsafe.
Syntax:
Both are same behavior:
e.g:
Constant Pointer : The location of pointer cannot be changed, but the data contained in the pointer can be changed
<Data type of pointer> * const <name of pointer>
E.g:
#Example 1: Pointer to constant content < Pointer to constant integer>
Static variable are accessed using static member function.
Thumb rule:
Static member variable must be initialized outside of the class using '::' scope resolution operator.
Other we will end up with the compiler errors.
<return Type> Classname :: <static variable> = Any value;
e.g: int Base :: static_variable = 0;
Static Member function:
If the static member variables are public, we can access them directly using the class name and the scope resolution operator
What if static member variables are private, how to access them? The answer is using static member functions.
static member variables, static member functions are not attached to any particular object.
It always accessed using class name::<static_variable> or class name::<static_function>
What happens if you don't initialize the static variable?
int Base :: static_variable = 0; You will end up with the unreferenced errors.
Can i intialise the static variable inside class?
C++ ISO forbids to initialize the static variables, but there is provision for const static variables.
class Base
{
public:
static const int var=3;
};
Here you don't need to initialize outside the class.
Example 1: With out static member
#include <iostream>
using namespace std;
class Base
{
public:
int data;
void displayData();
};
void Base ::displayData()
{
cout<<" The object address is:\t"<<this<<"\t and data is :"<<data<<endl;
}
int main()
{
Base obj1, obj2;
obj1.data=20;
obj2.data=30;
obj1.displayData();
obj2.displayData();
return 0;
}
Output:
The object address is: 0xbfa6d6f8 and data is :20
The object address is: 0xbfa6d6fc and data is :30
Observe above: the variable is not shared across the objects.
Thumb rule:
static member variable must be initialized outside of the class using '::' scope resolution operator.
Other we will end up with the compiler errors.
#include <iostream>
using namespace std;
class Base
{
public:
static int data;
static void displayData();
};
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int main()
{
Base::data=20;
Base::data=30;
Base::displayData();
Base::displayData();
return 0;
}
Notes: Static Variables and static function can be accessed only with class name and scope resolution (::), It doesn't have neither any objects nor "this" pointer for static variables and functions.
Output:
/tmp/ccEKEINg.o: In function `Base::displayData()':
singleto.cpp:(.text+0x9): undefined reference to `Base::data'
/tmp/ccEKEINg.o: In function `main':
singleto.cpp:(.text+0x4b): undefined reference to `Base::data'
singleto.cpp:(.text+0x55): undefined reference to `Base::data'
collect2: error: ld returned 1 exit status
"Why compilation Errors":
Static variables are not initialized explicitly as "int Base::data=0".
If you don't declare, will end up with the errors.
#include <iostream>
using namespace std;
class Base
{
public:
static int data;
static void displayData();
};
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int Base :: data=0; // Intialise the static Variables.
int main()
{
Base::data=20;
Base::data=30;
Base::displayData();
Base::displayData();
return 0;
}
Output:
The data is :30
The data is :30
#Example : Const static variable can be initialize inside class.
#include <iostream>
using namespace std;
class Base
{
public:
static const int data = 30; // You can intialise inside class, there is no need explicit.
static void displayData();
};
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int main()
{
Base::displayData();
return 0;
}
Output:
The data is :30
#Example: counter Variable is shared by all Base class objects,
When a new Base object is created, the constructor called and set to the current value of the counter and increments to the next object. This way to generate the unique values for the objects.
#include <iostream>
using namespace std;
class Base
{
static int counter;
int data;
public:
Base()
{
data=counter++;
}
void displayData();
};
int Base::counter=0;
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int main()
{
Base ob1, ob2, ob3;
// The static variable is kept in between functional values.
ob1.displayData();
ob2.displayData();
ob3.displayData();
return 0;
}
Output:
The data is :0
The data is :1
The data is :2
Notes: Store the value and then increment for the next object.
#EXAMPLE: VERY IMPORTANT FOR SINGLETON IMPLEMENTATION
#include<iostream>
using namespace std;
int &func();
int &func()
{
static int a;
int *a1=new int;
cout<<"The address of static variable\t:"<<&a<<endl;
cout<<"The address of pointer variable\t:"<<a1<<endl;
cout<<"The value pointed by the pointer\t:"<<*a1<<endl;
a1=&a;
cout<<"The address pointed by the pointer variable\t:"<<&(*a1)<<endl;
return *a1;
}
int main()
{
cout<<"The function address value : First Call\t"<<&func()<<endl;
cout<<"The function address value : Second Call \t"<<&func()<<endl;
cout<<"The function value with out Reference : Third Call \t"<<func()<<endl;
return 0;
}
Output:
The address of static variable :0x804a0d4
The address of pointer variable :0x90cc008
The value pointed by the pointer :0
The address pointed by the pointer variable :0x804a0d4
The function address value : First Call 0x804a0d4
The address of static variable :0x804a0d4
The address of pointer variable :0x90cc018
The value pointed by the pointer :0
The address pointed by the pointer variable :0x804a0d4
The function address value : Second Call 0x804a0d4
The address of static variable :0x804a0d4
The address of pointer variable :0x90cc028
The value pointed by the pointer :0
The address pointed by the pointer variable :0x804a0d4
The function value with out Reference : Third Call 0
Notes:
The static member variable is created once in memory and same memory is used for subsequent calls.
It shall not be created in memory for another function call. The same memory is been used for all function calls.
int &func()
{
static int a;
return a;
}
or
int &func()
{
static int a;
int *p= new int;
p=&a;
return p;
}
q= func() // It returns 0x0
q= &func() // It returns the address (&a or &(*p)) both are same.
this pointer holds the address of the object. "this" pointer is hidden and it is been passed as argument to the non static member functions.
There is no "this" pointer for the static function, since the static variable and static member can't be accessed using objects and It is accessed by using <classname>::<static_variable> or <classname>::<static_function>.
this pointer is hidden argument passed as shown below.
#include<iostream>
using namespace std;
class base
{
int data;
public:
base(int a)
{
data=a;
}
void display()
{
cout<<"The value of data\t"<<data<<endl;
}
};
int main()
{
base ob(2); // *this = &ob contains address of ob
ob.display();
}
Note #1:
This calling function ob.display() having no arguments, but actually it has one.
When compiled, the compiler converts as display(&ob)
Note #2:
void display() is converted by the compiler into:
void display(base* const this) { cout<<"The value of data\t"<<this->data<<endl; }
When we need to call Explicitly "this pointer" ?
When you have a constructor (or member function) that has a parameter with the same name as a member variable, you can differentiate them by using “this”.
#include<iostream>
using namespace std;
class base
{
int data;
public:
base(int data)
{
data=data;
}
void display()
{
cout<<"The value of data\t"<<data<<endl;
}
};
int main()
{
base ob(2);
ob.display();
}
Output:
Compilation shall be sucessful, but the output is undefined value or junk Value.
How to overcome this
-----------------------------
#include<iostream>
using namespace std;
class base
{
int data;
public:
base(int data)
{
this->data=data;
}
void display()
{
cout<<"The value of data\t"<<data<<endl;
}
};
int main()
{
base ob(2);
ob.display();
}
Output:
2.
Notes: In the constructor you can observe, this is been used here.
-------------------------------------------------------
Second USE Case ::: Chaining of the objects.
-------------------------------------------------------
It allow a series of functions to be “chained” together, so several functions can be called on the same object.
e.g: ob.set(2).add(4).display()
Before this please understand the function returning the reference:
-------------------------------------------------------------------
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
this->counter = 0;
}
Base get_copy()
{
return *this;
}
Base& get_copy_as_reference()
{
return *this;
}
Base* get_pointer()
{
return this;
}
void increment_counter()
{
this->counter++;
}
void display()
{
cout << this->counter << endl;
}
private:
int counter;
};
int main()
{
Base ob;
ob.increment_counter();
ob.display();
ob.get_copy().increment_counter();
ob.display();
ob.get_copy_as_reference().increment_counter();
ob.display();
ob.get_pointer()->increment_counter();
ob.display();
return 0;
}
Output:
1
1
2
3
Notes:
From the above example, it is evident that,
Base get_copy()
{
return *this;
}
-> shall Create the New Object or clone of the existing object. Whereas
Base& get_copy_as_reference()
{
return *this;
}
Base* get_pointer()
{
return this;
}
It will return the local object address (Same object address) and it won't create new object. So that's why the output values are 2 and 3.
Reference function return the address of same object to the function (ob.get_copy_as_reference().increment_counter())
How reference been used in chain of function calls?
When a reference to a local object is returned, the returned reference can be used to chain function calls on a single object.
#include <iostream>
using namespace std;
class Base
{
public:
Base &set_data(int j)
{
counter=2;
return *this;
}
Base &add_value(int i)
{
counter +=i;
return *this;
}
void display()
{
cout << counter << endl;
}
private:
int counter;
};
int main()
{
Base ob;
ob.set_data(2).add_value(10).display();
return 0;
}
Output:
12 // Local object address or reference is being returned.
Where all objects have their own lifecycle and there is no owner
The relationship may be unidirectional or bidirectional or indirect association, so that the two objects are known each other.
Other words, one class have a relationship with an other class object. e.g.: Foo class uses Bar object
Examples:
> Doctor and Patient:
A doctor can see many patients in a day, and a patient can see many doctors in a day for second opinion. Doctor uses a patient to earn income, patient uses a doctor for health checkup.
> Teacher and student:
Multiple students can associate with single teacher and single student can associate with multiple teachers.
> Engineer Uses a Swipe card
Software Engineer uses a Swipe card to enter the X company office premises.
Important Point is: There is no ownership between the objects and both have their own lifecycle.
Both can be created and deleted independently.
One–to–one Associations
One–to–many Associations
The association is represented by the following symbol in UML:
Example: A Student and a Faculty are having an association.
Unidirectional Relationship
unidirection_assoc.cpp
------------------------------
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class student
{
private:
string m_student_name;
public:
student(string name):m_student_name(name)
{
}
string get_student_name() const
{
return m_student_name;
}
};
class professor
{
private:
/* Association */
// One Professor Many Students 1 to *(many) Association
// 1 to many students
vector<student *> m_students;
string m_professor_name;
public:
professor(string name):m_professor_name(name)
{
}
// Add Students
void add_students(student *st)
{
m_students.push_back(st);
}
void display()
{
unsigned int length = m_students.size();
cout<<"Professor :"<<m_professor_name<<endl;
for (unsigned int count = 0; count < length; ++count)
cout<<m_students[count]->get_student_name()<<' ';
}
};
int main()
{
student *s1= new student ("RAM");
student *s2= new student ("KRISH");
student *s3= new student ("JAY");
professor *p1=new professor ("RISHI");
p1->add_students(s1);
p1->add_students(s2);
p1->add_students(s3);
p1->display();
// No one is the owner
delete s1;
delete s2;
delete s3;
// We can create and destory the objects
// independently.
delete p1;
return 0;
}
Bidirectional Relationship
bidirectional_assoc.cpp
------------------------------
#include<iostream>
#include<string>
#include<vector>
using namespace std;
// Class Forward Declartion
class professor;
class student
{
private:
string m_student_name;
vector<professor *> m_professor;
public:
student(string name):m_student_name(name)
{
}
string get_student_name() const
{
return m_student_name;
}
// Add professsors
void add_professsors(professor *pf)
{
m_professor.push_back(pf);
}
void display_students();
};
class professor
{
private:
/* Association */
// One Professor Many Students 1 to *(many) Association
// many to many students
vector<student *> m_students;
string m_professor_name;
public:
professor(string name):m_professor_name(name)
{
}
// Add Students
void add_students(student *st)
{
m_students.push_back(st);
//Student add the professor
st->add_professsors(this);
}
string get_professor_name() const
{
return m_professor_name;
}
void display()
{
unsigned int length = m_students.size();
cout<<"In Professor class, professor Name :"<<m_professor_name<<endl;
cout<<"Student name :"<<endl;
for (unsigned int count = 0; count < length; ++count)
cout<<m_students[count]->get_student_name()<<' '<<endl;
}
};
void student::display_students()
{
unsigned int length = m_professor.size();
cout<<"In Student class, Student Name :"<<m_student_name<<endl;
cout<<"Professor Name :"<<endl;
for (unsigned int count = 0; count < length; ++count)
cout<<m_professor[count]->get_professor_name()<<' '<<endl;
}
int main()
{
student *s1= new student ("RAM");
student *s2= new student ("KRISH");
student *s3= new student ("JAY");
professor *p1=new professor ("RISHI");
professor *p2=new professor ("DAVID");
professor *p3=new professor ("THOMAS");
p1->add_students(s1);
p1->add_students(s2);
p2->add_students(s1);
p2->add_students(s3);
p3->add_students(s2);
p3->add_students(s3);
p1->display();
p2->display();
p3->display();
cout<<endl;
s1->display_students();
s2->display_students();
s3->display_students();
// No one is the owner
delete s1;
delete s2;
delete s3;
// We can create and destory the objects
// independently.
delete p1;
delete p2;
delete p3;
return 0;
}
Indirect Association Relationship
indirect_assoc.cpp
-------------------------
#include<iostream>
#include<string>
using namespace std;
class Book
{
private:
string book_name;
int book_id;
public:
Book(string name, int id): book_name(name), book_id(id)
{
}
string get_book_name()
{
return book_name;
}
int get_book_id()
{
return book_id;
}
};
class Library
{
private:
static Book book_list[5];
Library();
public:
static Book *get_book(int id)
{
for(int count=0; count <5; count++)
{
if(book_list[count].get_book_id() == id)
return &(book_list[count]);
}
return NULL;
}
};
Book Library::book_list[5]={Book("C++", 1), Book("Java", 2), Book(".NET", 3), Book("C#", 4), Book("OS", 5)};
class User
{
private:
string user_name;
int m_book_id;
public:
User(string name, int id):user_name(name), m_book_id(id)
{
}
int get_book_id()
{
return m_book_id;
}
string get_user_name()
{
return user_name;
}
};
int main()
{
User user_obj("muni", 1);
int book_id= user_obj.get_book_id();
Book *book_obj= Library::get_book(book_id);
cout<<"The Book Name : "<< book_obj->get_book_name()<<endl;
cout<<"The Book Id : "<<book_obj->get_book_id()<<endl;
}
Aggregation (HAS-A Relationship): It is Special form of Association.
A directional association between objects. When an object ‘has-a’ another object, then you have got an aggregation between them. Aggregation is also called a “Has-a” relationship
Where all objects have their own lifecycle but there is ownership and child objects can not belong to another parent object.
Let’s take an example of Department and teacher. A single teacher can not belong to multiple departments, but if we delete the department teacher object will not be destroyed. We can think about it as a “has-a” relationship.
E.g: Employee has a relation ship with the Address.
I have an object which I've borrowed from someone else. When Foo dies, Bar may live on
Aggregation is also referred to as a Weak Association and is represented by the following symbol:
unidirectional_aggre.cpp
#include<iostream>
#include<string>
using namespace std;
class Address
{
private:
string state;
string city;
string street;
public:
Address(string street, string city, string state)
{
this->street=street;
this->city=city;
this->state=state;
}
string get_street_name(){ return street; }
string get_city_name(){ return city; }
string get_state_name(){ return state; }
};
class Employee
{
private:
string m_employee_name;
Address *m_employee_address;
public:
Employee(string name, Address *address):m_employee_name(name), m_employee_address(address){
}
void print_employee_details()
{
cout<<"Empolyee Name: "<< m_employee_name<<endl;
cout<<"Street name: "<<m_employee_address->get_street_name()<<" "<<"city name :"<<" " \
<<m_employee_address->get_city_name()<<" "<<"State_name :"<<" "<<m_employee_address->get_state_name()<<endl;
}
};
int main()
{
Address *addr_obj= new Address("OHIO DR", "PLANO", "TEXAS");
{
Employee emp_obj("RAM", addr_obj); emp_obj.print_employee_details();
} // Employee goes out of scope, still address object lives on
addr_obj->get_street_name();
addr_obj->get_city_name();
addr_obj->get_state_name();
delete addr_obj;
return 0;
}
Composition (HAS-A Relationship): It is strong type of Aggregation.
It is also called as The Death relationship
In this type of Aggregation the child object does not have their own life cycle. The child object's life depends on the parent's life cycle. Only the parent object has an independent life cycle. If we delete the parent object then the child object(s) will also be deleted.
object composition models a “has-a” relationship between two objects. A car “has-a” Engine. Your computer “has-a” CPU,. Human Body “has-a” heart
e.g.:
For example, the company and company location, a single company has multiple locations.
If we delete the company then all the company locations are automatically deleted.
The company location does not have their independent life cycle, it depends on the company object's life (parent object).
When a body is created, the heart is created too. When a person’s body is destroyed, their heart is destroyed too.
Because of this, composition is sometimes called a “death relationship”. unidirectional relationship, because the body knows about the heart. The UML representation of composition as:
Example: A class contains students. A student cannot exist without a class. There exists composition between class and students. The lifetimes of both the objects are the same
Foo class has a Bar object as data member.
Foo has a Bar object as data member -> Foo contains a Bar. It can't exist without it.
composition and aggregation
Compositions:
> use normal member variables > We Can use pointer values if the composition class automatically handles allocation/deallocation
> Responsible for creation/destruction of parts
Aggregations:
> Typically use pointer or reference members that point to or reference objects that live outside the scope of the aggregate class
> Not responsible for creating/destroying parts
unidirectional_compos.cpp
-----------------------------------
#include<iostream>
#include<string>
using namespace std;
/*
* Book
*/
class Book
{
string book_name;
int book_id;
public:
Book(string name, int id):book_name(name), book_id(id)
{
}
string get_book_name()
{
return book_name;
}
int get_book_id()
{
return book_id;
}
};
/*
* Library
*/
class Library
{
private:
Book m_book;
string m_library_name;
public:
Library(string name, Book book_obj): m_library_name(name), m_book(book_obj)
{
}
void display_library()
{
cout<<"The Library Name :"<< m_library_name<<endl;
cout<<"Book name :"<<m_book.get_book_name()<<endl;
cout<<"Book Id :"<<m_book.get_book_id()<<endl;
}
};
int main()
{
Library lib_ob("PLANO LIBRARY", Book("Devotional", 1233));
lib_ob.display_library();
return 0;
}
With Pointer Composition
-------------------------
#include<iostream>
#include<string>
using namespace std;
/*
* Engine
*/
class Engine
{
string engine_name;
int engine_id;
public:
Engine(string name, int id):engine_name(name), engine_id(id)
{
}
string get_engine_name()
{
return engine_name;
}
int get_engine_id()
{
return engine_id;
}
};
/*
* Car
*/
class Car
{
private:
Engine *m_engine;
string car_name;
public:
Car(string name): car_name(name)
{
m_engine = new Engine("X_POWER", 123);
}
~Car()
{
delete m_engine;
}
void display_car()
{
cout<<"The Car Name :"<< car_name<<endl;
cout<<"Engine name :"<<m_engine->get_engine_name()<<endl;
cout<<"Engine Id :"<<m_engine->get_engine_id()<<endl;
}
};
int main()
{
Car *car_obj= new Car("AUDI");
car_obj->display_car();
delete car_obj;
return 0;
}
Owner, lifetime, and child object:
Generalization:
This implies an "is a" relationship. One class is derived from another, the base class. Generalization is implemented as inheritance in C++. The derived class has more specialization. It may either override the methods of the base, or add new methods.
Dependency
Change in structure or behavior of a class affects the other related class, then there is a dependency between those two classes. It need not be the same vice-versa. When one class contains the other class it this happens.
Example:
#include<iostream>
#include<string>
using namespace std;
class Wheel
{
string wheel_name;
public:
Wheel(string name)
{
wheel_name=name;
}
string get_wheel()
{
return wheel_name;
}
};
class Car
{
string car_name;
public:
void get_car_wheel(Wheel &wheel_obj)
{
cout<<"The car wheel Type is"<<" "<<wheel_obj.get_wheel();
}
};
int main()
{
Wheel whel_obj("MRF");
Car car_obj;
car_obj.get_car_wheel(whel_obj);
return 0;
}
Realization
Realization is a relationship between the blueprint class and the object containing its respective implementation level details. This object is said to realize the blueprint class.
Realization specifies a contract between two or more types. Where one type (here Interface Imammals) defines the contract and the other type (Cat, Dog) promises to carry out.
Example:
will answer the below questions in another post.
7. Explain about string classes in C++?
8. What are Templates and why they are used?
11. What is Smart pointer in C++ 11 standard?
12. What are design pattern used in C++? Explain some of them?
14. Explain different types of inheritance in C++?
16. What do you mean by reference in C++?
17. What do you need to mention reference operator in C++ function? what are the advantages?
18. What are storage classes in C++?
19. What are access specifiers in C++?
21. Explain about the casting operators in C++?
22. Difference between Volatile vs Register keyword in C++?
23.Is it possible to have virtual constructors in C++?
24.What is STL? Explain the STL operations?
25. Difference between vector vs list?
26. What is memory leak and how to detect the memory leaks in C++?
27. Can we debug macros using GDB? How to debug the macros using GDB?
28. What is difference between macro and inline function? which is efficient?
29. What are the ways of intialise the data members of class?
30. What is Implicit and explicit conversion operator in C++?
32. What is friend function in C++?
33. Template class vs template function in C++?
34. What is list, dequeue in c++?
35. How to connect the database using C++?
36. What is operator overloading in C++?
37. What are the unit testing frameworks used in C++?
38. Explain me the file operations in C++?
39. What is Exception handling and how it is implemented in C++?
Database Questions:
1. Explain stored procedure and how it is implemented in database?
2. What is Normalization?
3. How to drop the table?
4. How to create/delete/update the Table?
5. How to remove particular column in a table?
6. How to insert the values in the Table?
7. How to optimise the database access with respect to application?
8. what is difference between RDMS (SQL) and NOSQL
1. What is copy Constructor?
Copy constructor is a special constructor used to create an copy of an object from existing object of same class.Why copy constructor is needed?
Copy constructor is needed when the class have any pointers of data. or any data members of class are pointers.
When is data members of class is allocated memory using dynamic memory allocation of new operator, then in order to create another object from existing object, it is mandate to use the user defined copy constructor.
What kind of copy does by copy constructor?
It does the deep copy.
What is the difference between shallow copy and deep copy?
Shallow copy is nothing but the assignment operator (a=b), it just copy the value of the variable to another, but it doesn't worry about the references.
object1= object2
Deep copy comes in to picture only when there are any pointers in the class and to create any new object from the existing object, we need to copy the object references (address) to create the exact copy of object from existing object.
class_name new_object= old_objectcopy constructor performs the deep copy.
How does the copy constructor signature looks like?
Class_name (const class_name &old_object)
class_name (volatile class_name &old_object)
class_name (class_name &old_object)
class_name (class_name &old_object, double = 1.0, int = 42)
class_name (class_name &old_object, double = 1.0)
class_name (volatile const class_name &old_object)
When does copy constructor is been called?
Base_class new_object= old_object
Base_class new_object(old_object)
new_object(old_object)
When an object is returned by value as below:
Base_class new_object= function(old_object)
What is implicit copy constructor and user define (explicit) copy constructor?
Default copy constructor or Implicit copy constructor. Implicit copy constructor also called as default copy constructor. The compiler will generate the default copy constructor.
If the programmer did not declared the copy constructor for a class, the compiler will add its own default copy constructor for the objects derived from that class.
Default copy constructor does a very simple operation, they will do a bit-wise (member-wise) copy of an object, which means that the object will be copied bit by bit.
#include<iostream>
#include<string>
using namespace std;
class Base
{
private:
int EmpId;
int age;
public:
Base(int a, int b);
};
Base :: Base(int a, int b)
{
EmpId =a;
age=b;
}
int main()
{
Base obj1(2, 20);
Base obj2=obj1; // Compiler creates Default Copy constructor
}
How Default or copy constructor Looks like?
Base::Base(const Base &Otherobject): EmpId (Otherobject.EmpId ), age (Otherobject.age)
{
}
Example #1
#include<iostream>
#include<string>
using namespace std;
class Base
{
private:
int EmpId;
int age;
public:
Base(int a, int b);
// Copy constructor
Base(const Base &otherObj);
void display();
};
Base :: Base(int a, int b)
{
cout<<" I am in the constructor"<<endl;
EmpId =a;
age=b;
}
// Default Copy constructor which does bit by bit copy (Shallow Copy)
// When there is Pointer variable it will lead to crash.
Base :: Base(const Base &otherObj)
{
cout<<" I am in the Copy constructor"<<endl;
EmpId =otherObj.EmpId;
age=otherObj.age;
}
void Base :: display()
{
cout<<"The EMPID and Age" <<"\t"<<EmpId<<"\t"<<age<<endl;
}
int main()
{
Base obj1(2, 20);
// Copy constructor
Base obj2=obj1;
obj2.display();
}
What happens if there is a pointer member variable in class?
There is a danger in copying an object bit by bit, if the object contains pointers since the pointer address will be copied in the process resulting in two different objects that share the same memory buffer.
You can imagine what will happen when two copies of an object calls their destructors one after the other. The first object that call its destructor will have no problems, since it will try to deallocate the pointer and succeed, but the second objects destructor try to de allocate a pointer which does not exist anymore and the whole application crashes!
Why you need user define (explicit) copy constructor?
If the object have pointers, then there is a need to have explicit or user defined copy constructor for deep copy.
- If you need a copy constructor, you also need a destructor and operator=
- If you need a copy constructor, it's because you need something like a deep copy, or some other management of resources. Thus is is almost certain that you will need a destructor and override the assignment operator.
Example #2
#include<iostream>
#include<string>
using namespace std;
class Base
{
private:
int EmpId;
int age;
// Pointer Data
int *p;
public:
// Constructor
Base(int a, int b);
//Copy Constructor
Base(const Base &Otherobj);
void display();
//Destructor
~Base();
};
Base :: Base(int a, int b)
{
EmpId =a;
age=b;
p= new int;
*p=10 ;
cout<<"I am in the constructor"<<"\t"<<p<<endl;
}
Base :: ~Base()
{
delete p;
}
// User Defined Copy constructor
// If there is no user defined constructor, then destructor calls twice
// Leads to crash.
Base::Base(const Base &Otherobj):EmpId(Otherobj.EmpId), age(Otherobj.age)
{
p = new int;
*p = *Otherobj.p;
cout<<" I am in the copy constructor "<<"\t"<<p<<endl;
}
void Base:: display()
{
cout<<" Print the Object address"<<this<<endl;
cout<<"The value of EmpID, age, Name"<<EmpId<<"\t"<<age<<"\t"<<p<<endl;
}
int main()
{
// Calls Normal constructor
Base obj1(2, 20);
// Calls User Defined Copy constructor
Base obj2=obj1;
obj1.display();
obj2.display();
}
#include<string>
using namespace std;
class Base
{
private:
int EmpId;
int age;
// Pointer Data
int *p;
public:
// Constructor
Base(int a, int b);
//Copy Constructor
Base(const Base &Otherobj);
void display();
//Destructor
~Base();
};
Base :: Base(int a, int b)
{
EmpId =a;
age=b;
p= new int;
*p=10 ;
cout<<"I am in the constructor"<<"\t"<<p<<endl;
}
Base :: ~Base()
{
delete p;
}
// User Defined Copy constructor
// If there is no user defined constructor, then destructor calls twice
// Leads to crash.
Base::Base(const Base &Otherobj):EmpId(Otherobj.EmpId), age(Otherobj.age)
{
p = new int;
*p = *Otherobj.p;
cout<<" I am in the copy constructor "<<"\t"<<p<<endl;
}
void Base:: display()
{
cout<<" Print the Object address"<<this<<endl;
cout<<"The value of EmpID, age, Name"<<EmpId<<"\t"<<age<<"\t"<<p<<endl;
}
int main()
{
// Calls Normal constructor
Base obj1(2, 20);
// Calls User Defined Copy constructor
Base obj2=obj1;
obj1.display();
obj2.display();
}
2. Difference between New/Delete vs Malloc/Free?
Answer:New and Malloc is used for allocating memory dynamically ( during run time)
- The most relevant difference is that the new operator allocates memory then calls the constructor and delete calls the destructor then deallocates the memory.
- malloc and free just allocate and release raw memory
Some of other differences:
------------
new/delete
-------------
Allocate/release memory
Memory allocated from 'Free Store'
Returns a fully typed pointer.
new (standard version) never returns a NULL (will throw on failure)
Are called with Type-ID (compiler calculates the size)
Has a version explicitly to handle arrays.
Reallocating (to get more space) not handled intuitively (because of copy constructor).
Whether they call malloc/free is implementation defined.
Can add a new memory allocator to deal with low memory (set_new_handler)
operator new/delete can be overridden legally
constructor/destructor used to initialize/destroy the object
--------------
malloc/free
--------------
Allocates/release memory
Memory allocated from 'Heap'
Returns a void*
Returns NULL on failure
Must specify the size required in bytes.
Allocating array requires manual calculation of space.
Reallocating larger chunk of memory simple (No copy constructor to worry about)
They will NOT call new/delete
No way to splice user code into the allocation sequence to help with low memory.
malloc/free can NOT be overridden legally
------------
new/delete
-------------
Allocate/release memory
Memory allocated from 'Free Store'
Returns a fully typed pointer.
new (standard version) never returns a NULL (will throw on failure)
Are called with Type-ID (compiler calculates the size)
Has a version explicitly to handle arrays.
Reallocating (to get more space) not handled intuitively (because of copy constructor).
Whether they call malloc/free is implementation defined.
Can add a new memory allocator to deal with low memory (set_new_handler)
operator new/delete can be overridden legally
constructor/destructor used to initialize/destroy the object
--------------
malloc/free
--------------
Allocates/release memory
Memory allocated from 'Heap'
Returns a void*
Returns NULL on failure
Must specify the size required in bytes.
Allocating array requires manual calculation of space.
Reallocating larger chunk of memory simple (No copy constructor to worry about)
They will NOT call new/delete
No way to splice user code into the allocation sequence to help with low memory.
malloc/free can NOT be overridden legally
Source: http://stackoverflow.com/questions/240212/what-is-the-difference-between-new-delete-and-malloc-free
3. Explain how to implement the new and delete in C++?
Answer:new:
pointer = new type
pointer = new type [number_of_elements]
The first expression is used to allocate memory to contain one single element of type
type
. The second one is used to allocate a block (an array) of elements of type
type
, where number_of_elements
is an integer value representing the amount of these. For example:int *p = new int; // allocates 1 Uninitialized int
int *q = new int[4]; // allocates 4 Uninitialized int's
int *p = new int(); // allocates 1 int and initialized to Zero
int *q = new int[4](); // allocates 4 int's and initialized to Zero's
In the above example, the first expression is used to allocate memory to contain one single element of type
int
.the system dynamically allocates space for four elements of type
int
and returns a pointer to the first element of the sequence, which is assigned to q
(a pointer). Therefore, q
now points to a valid block of memory with space for four elements of type int
.delete:
delete pointer;
delete[] pointer;
The first statement releases the memory of a single element allocated using new.
Second one releases the memory allocated for arrays of elements using new and a size in brackets ([])
delete p;
delete [] q;
As mentioned above, new never returns NULL, it throws an exception as bad_alloc and it should be handled using catch(std::bad_alloc&)
try {
char* c = new char[100];
} catch (std::bad_alloc&) {
// Handle error
}
Another method is known as nothrow
, and what happens when it is used is that when a memory allocation fails, instead of throwing a bad_alloc
exception or terminating the program, the pointer returned by new
is a null pointer, and the program continues its execution normally.Specify a special object called nothrow, declared in header <new>, as argument for new:
int *s;
s = new (nothrow) int [5]; In this case, if the allocation of this block of memory fails, the failure can be detected by checking if s is a null pointer:
int * s;
s = new (nothrow) int [5];
if (s == nullptr) { // There is no NULL, validate with nullptr
// error assigning memory. Take measures.
}
In the new compilers, there is no need to check pointer for null.
Base * object = new Base(); // No need to check if object is null
or Simply write using the smart pointers.
auto p = make_unique<Base>(); // No need to check if object is null
Example #1:
class Base {
public:
Base (int c, int r);
// no default constructor
// ...
};
class Y {
public:
Y(); // default constructor
// ...
};
void func(int n)
{
void* p1 = malloc(40); // allocate 40 (uninitialized) bytes
int* p2 = new int[10]; // allocate 10 uninitialized ints
int* p3 = new int(10); // allocate 1 int initialized to 10
int* p4 = new int(); // allocate 1 int initialized to 0
int* p4 = new int; // allocate 1 uninitialized int
Base * pc1 = new Circle(10,10); // allocate a Circle constructed
// with the specified argument
Base * pc2 = new Base; // error no default constructor
Y* px1 = new Y; // allocate a default constructed Y
Y* px2 = new Y(); // allocate a default constructed Y
Y* px2 = new Y[10]; // allocate 10 default constructed Y
// ...
}
Example #2:
#include<iostream>
using namespace std;
class base
{
public:
base(){ cout<<"Constructor is called"<<endl;}
~base() { cout<<"destructor is called"<<endl;}
};
int main()
{
int *q= new int; // allocate 1 int which is uninitialized
int *p= new int(10); // allocate 1 int which is initialized to 10
base *b = new base(); // Constructor is called
base *obj= new base[2]; // Two objects created and two times the constructor is called.
cout<<" The value of q is"<<endl<<*q<<endl;
cout<<" The value of p is"<<endl<<*p<<endl;
delete b; // Destructor is called
delete [] obj; // 2 times destructor is called.
delete q; // Frees the memory
delete p; // Frees the memory
return 0;
}
Some more tips:
- Delete can't be used for the memory allocated using MALLOC.
- Delete [] p should be used for array of elements.
- There is no need to validate the pointer before calling Delete pointer
- With in a same block, if Delete is called then it is not efficient technique.
- Use the smart pointers to avoid the memory leaks.
How to create multidimensional array of pointers using New operator?
As we have seen,
Step 1: Declare the double pointer of respective type.
Step 2: Intialise the memory for the double pointers, How many pointers you need (new *[4])
Step 3: Allocate the Memory for each array of pointer and store the data.
Example 3#
#include<iostream>
#include<string>
using namespace std;
int main()
{
int **array;
//Allocate the memory for the double pointer array= new int*[2];
// Allocate the memory for the each array pointer
// Each pointer holds 5 int's
for (int i=0; i<2; i++)
array[i] = new int[3];
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cin>>array[i][j];
}
cout<<"Loop ends"<<endl;
}
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cout<<"\t"<<array[i][j];
}
cout<<endl<<"Loop end:"<<i<<endl;
}
// Inner pointer array deletion
for (int i=0; i<2; i++)
delete[] array[i];
// Double pointer memory deletion
delete [] array;
return 0;
}
What is virtual function?
Simple Answer is, A function is defined with a virtual Keyword is called Virtual Function. (Interviewer will get shock with our smart answer).
virtual Function is a base class function whose functionality is overridden in the derived class.
And which tells the compiler to perform Late Binding on this function. Virtual Keyword is used to make a member function of the base class Virtual.
What is late binding and static binding?
Virtual function does the late binding.
Late binding:
which function need to call is determined during run time rather than compile time. This is also called as run time polymorphism.
Static Binding:
Which function call is determined during compile time by the compiler is called early binding. This is called compile time polymorphism.
What is VTABLE and Virtual Pointer and its implementation?
Virtual functions are internally implemented using Virtual Table and Virtual Pointers.
Virtual Table [VTABLE or Virtual Function Table] : It is Look up Table of functions used to resolve the function calls in a late binding.
Let's understand with VTABLE and VPTR with simple example : [Source : http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/]
Virtual function Example #:
class Base
{
public:
virtual void func1() {};
virtual void func2() {};
};
class Derived1: public Base
{
public:
virtual void func1() {};
};
class Derived2: public Base
{
public:
virtual void func2() {};
};
In the above example: There are three classes present Base1, Derived1, Derived2.
Step 1: The compiler will set up 3 virtual tables: one for Base, one for Derived1,
and one for Derived2.
Step 2: The compiler also adds a hidden pointer to the most base class that uses
virtual functions.
In our example, it adds hidden virtual pointer to the base class, as mentioned below.
class Base
{
public:
FunctionPointer *__vptr;
virtual void func1() {};
virtual void func2() {};
};
Step 3: When the class object is created, virtual pointer (*__vptr) is set to point to the virtual
table for that class.
In our example, when a Base class object is created, *__vptr is set to point to the virtual
table of Base Class. When Derived 1 and Derived 2 objects are created, then *__vptr is set
to point to the Derived1 and Derived2 virtual tables respectively.
Step 4: Then what is there in the virtual Table.
Virtual table contains the virtual functions that are defined in the class There are only
two virtual functions here, each virtual table will have two entries (one for func1(), and
one for func2()).
How it works? Let's explain through example:
Base Class:
As we have seen,
int *P = new int[4] ->
new int[4];
calls operator new function()- allocates a memory for 4 integers.
- returns a reference to this memory.
Step 1: Declare the double pointer of respective type.
Step 2: Intialise the memory for the double pointers, How many pointers you need (new *[4])
Step 3: Allocate the Memory for each array of pointer and store the data.
int **p;
// 4 array of pointers.
p = new int*[4]; // dynamic `array (size 4) of pointers to int`
for (int i = 0; i < 4; ++i) {
p[i] = new int[10];
// each i-th pointer is now pointing to dynamic array (size 10) of actual int values
}
How to free the memory
- For one dimensional array,
// need to use the delete[] operator because we used the new[] operator
delete[] p; //free memory pointed by p;
- For 2d Array,
// need to use the delete[] operator because we used the new[] operator
for(int i = 0; i < 4; ++i){
delete[] p[i];//deletes an inner array of integer;
}
delete[] p; //delete pointer holding array of pointers;
Example 3#
#include<iostream>
#include<string>
using namespace std;
int main()
{
int **array;
//Allocate the memory for the double pointer array= new int*[2];
// Allocate the memory for the each array pointer
// Each pointer holds 5 int's
for (int i=0; i<2; i++)
array[i] = new int[3];
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cin>>array[i][j];
}
cout<<"Loop ends"<<endl;
}
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cout<<"\t"<<array[i][j];
}
cout<<endl<<"Loop end:"<<i<<endl;
}
// Inner pointer array deletion
for (int i=0; i<2; i++)
delete[] array[i];
// Double pointer memory deletion
delete [] array;
return 0;
}
4. What is virtual function? Explain how it is implemented?
It is polymorphism technique which does the run time polymorphism.What is virtual function?
Simple Answer is, A function is defined with a virtual Keyword is called Virtual Function. (Interviewer will get shock with our smart answer).
virtual Function is a base class function whose functionality is overridden in the derived class.
And which tells the compiler to perform Late Binding on this function. Virtual Keyword is used to make a member function of the base class Virtual.
What is late binding and static binding?
Virtual function does the late binding.
Late binding:
which function need to call is determined during run time rather than compile time. This is also called as run time polymorphism.
Static Binding:
Which function call is determined during compile time by the compiler is called early binding. This is called compile time polymorphism.
What is VTABLE and Virtual Pointer and its implementation?
Virtual functions are internally implemented using Virtual Table and Virtual Pointers.
Virtual Table [VTABLE or Virtual Function Table] : It is Look up Table of functions used to resolve the function calls in a late binding.
- If a classes have virtual functions then each class shall have its own virtual table added by the compiler and also it also adds the Virtual pointer (vptr) in the constructor.
Let's understand with VTABLE and VPTR with simple example : [Source : http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/]
Virtual function Example #:
class Base
{
public:
virtual void func1() {};
virtual void func2() {};
};
class Derived1: public Base
{
public:
virtual void func1() {};
};
class Derived2: public Base
{
public:
virtual void func2() {};
};
In the above example: There are three classes present Base1, Derived1, Derived2.
Step 1: The compiler will set up 3 virtual tables: one for Base, one for Derived1,
and one for Derived2.
Step 2: The compiler also adds a hidden pointer to the most base class that uses
virtual functions.
In our example, it adds hidden virtual pointer to the base class, as mentioned below.
class Base
{
public:
FunctionPointer *__vptr;
virtual void func1() {};
virtual void func2() {};
};
Step 3: When the class object is created, virtual pointer (*__vptr) is set to point to the virtual
table for that class.
In our example, when a Base class object is created, *__vptr is set to point to the virtual
table of Base Class. When Derived 1 and Derived 2 objects are created, then *__vptr is set
to point to the Derived1 and Derived2 virtual tables respectively.
Step 4: Then what is there in the virtual Table.
Virtual table contains the virtual functions that are defined in the class There are only
two virtual functions here, each virtual table will have two entries (one for func1(), and
one for func2()).
How it works? Let's explain through example:
Base Class:
- Base class object can only access to the members of Base class.
- Base has no access to Derived1 or Derived2 functions.
- Consequently, the entry for func1 points to Base::func1(), and the entry for function2 points to Base::func2().
- Derived1 class Object can access members of both Derived1 and Base classes.
- Derived1 class has overridden func1(), making Derived1::func1() more derived than Base::funct1().
- Consequently, the entry for func1 points to Derived1::func1(). D1 hasn’t overridden func2(), so the entry for func2 will point to Base::func2().
- The virtual table for Derived2 is similar to Derived1, except the entry for func1 points to Base::function1(), and the entry for function2 points to Derived2::func2().
What happens when class objects created:
Case 1:
Derived1 d1;
d1-> vptr points to the virtual Table of Derived1 class.
Case 2:
Derived1 d1;
Base *bp;
bp=&d1;
Even tough the bp is base pointer, it is pointing to address of derived class object through
which it access the virtual table of Derived1 class.
bp->vptr points to the virtual Table of Derived1 class.
Example Program #1:
#include<iostream>
using namespace std;
class Bank
{
public:
virtual void interestRate()
{
cout<< "BASE Interest Rate is Zero"<<endl;
}
};
class stateBank : public Bank
{
public:
//Derived the functionality of BANK class
virtual void interestRate() // or void interestRate()
{
cout<< "STATE BANK INTEREST RATE: 9.5%"<<endl;
}
};
class indianBank : public Bank
{
public:
// Derived the functionality of BANK class
virtual void interestRate() // or void interestRate()
{
cout<< "INDIAM BANK INTEREST RATE: 10.5%"<<endl;
}
};
int main()
{
Bank *bp, bObj;
stateBank st;
indianBank indObj;
// Upcasting
bp= &st; // Upcasting
bp->interestRate();
bp= &indObj; // Upcasting
bp->interestRate();
bp=&bObj;
bp->interestRate();
st.interestRate();
indObj.interestRate();
return 0;
}
Output:
STATE BANK INTEREST RATE: 9.5%
INDIAM BANK INTEREST RATE: 10.5%
BASE Interest Rate is Zero
STATE BANK INTEREST RATE: 9.5%
INDIAM BANK INTEREST RATE: 10.5%
Example Program #2:
#include<iostream>
using namespace std;
class Fruit
{
public:
virtual void color()
{
cout<< "color is based on Type Fruit "<<endl;
}
virtual void taste()
{
cout<< "Taste is based on Type Fruit "<<endl;
}
};
class Apple : public Fruit
{
public:
//Derived the functionality of BANK class
virtual void color()
{
cout<< "Apple color is RED"<<endl;
}
};
class Mango : public Fruit
{
public:
virtual void taste()
{
cout<< "Mango Taste is Yummy"<<endl;
}
};
int main()
{
Fruit *fp;
Apple ap;
Mango mang;
// Upcasting
fp= ≈ // Upcasting
fp->color();
fp->taste();
fp= &mang; // Upcasting
fp->color();
fp->taste();
return 0;
}
fp->color();
fp->taste();
return 0;
}
Output:
Apple color is RED
Taste is based on Type Fruit
color is based on Type Fruit
Mango Taste is Yummy
#include<iostream>
using namespace std;
class Base // >>> Parent Class or Super Class
{
public:
Base()
{
cout<<"Base Constructor is called\n";
}
~Base()
{
cout<<"Base Destructor is called\n";
}
};
class Derived: public Base // >>> Sub Class or Derived Class or Child Class
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived Destructor is called\n";
}
};
int main()
{
Base b; // Base object is created
return 0;
}
Output:
Base Constructor is called
Base Destructor is called
Apple color is RED
Taste is based on Type Fruit
color is based on Type Fruit
Mango Taste is Yummy
5. How is the order of constructor and destructor calls using Inheritance?
- Whenever any class is derived (or inherited) from another class, then that class be called as sub class or child class.
- The class from which other class is derived called as parent class or super class.
#include<iostream>
using namespace std;
class Base // >>> Parent Class or Super Class
{
public:
Base()
{
cout<<"Base Constructor is called\n";
}
~Base()
{
cout<<"Base Destructor is called\n";
}
};
class Derived: public Base // >>> Sub Class or Derived Class or Child Class
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived Destructor is called\n";
}
};
int main()
{
Base b; // Base object is created
return 0;
}
Output:
Base Constructor is called
Base Destructor is called
Inheritance Rules:
Rule # 1 : Order of Constructor Call
- Base class constructors are always called in the derived class constructors.
- Whenever we create derived class object, first the base class default constructor is executed and then the derived class's constructor be called.
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
};
int main()
{
Derived d;
return 0;
}
Output:
Base Constructor is called
Derived Constructor is called
Derived Constructor is called
Who is responsible for calling the constructors?
Constructors are not callable by the user. Only compiler can call constructors.
The compiler will call the constructors in a very specific order defined
by the language specification, regardless of the order in which you
specify the initializers.
The base class constructors are always called
first , then the constructors of member subobjects are called.
Inheritance Example 2# With Derived class constructor having Parameters
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base Constructor is called\n";
}
};
class Derived: public Base
{
int a;
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
Derived(int j)
{
a=j;
cout<<"Derived Constructor with one parameter is called"<<"\t"<<a<<endl;
}
};
int main()
{
Derived d1;
Derived d2(2);
return 0;
}
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base Constructor is called\n";
}
};
class Derived: public Base
{
int a;
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
Derived(int j)
{
a=j;
cout<<"Derived Constructor with one parameter is called"<<"\t"<<a<<endl;
}
};
int main()
{
Derived d1;
Derived d2(2);
return 0;
}
Output:
Base Constructor is called
Derived Constructor is called
Base Constructor is called
Derived Constructor with one parameter is called 2
Base Constructor is called
Derived Constructor is called
Base Constructor is called
Derived Constructor with one parameter is called 2
How to specify on derived constructor which Base constructor to be called?
One can specify on derived constructor which Base constructor to be called, if not the default one will be executed. (or)Base class constructors are automatically called for you if they have no argument.
If you want to call a Base class constructor with an argument, you must use the subclass's (derived) constructor initialization list.
Inheritance Example 4# Specify which Base constructor to be called.
#include<iostream>
using namespace std;
class Base
{
int a;
public:
Base() // This will not be called.
{
cout<<"Default Constructor is called\n";
}
Base(int j)
{
a=j;
cout<<"Base Constructor is called\t"<<a<<endl;
}
};
class Derived: public Base
{
int b;
public:
Derived(int j): Base(j)
{
b=j;
cout<<"Derived Constructor with one parameter is called\t"<<b<<endl;
}
};
int main()
{
Derived d2(2);
return 0;
}
Output:
Base Constructor is called 2
Derived Constructor with one parameter is called 2
Inheritance Example 5#
#include<iostream>
using namespace std;
class Base
{
int a;
public:
Base(int j)
{
a=j;
cout<<"Base Constructor is called\t"<<a<<endl;
}
};
class Derived: public Base
{
int b;
public:
Derived(int j1, int j2): Base(j1)
{
b=j2;
cout<<"Derived Constructor with one parameter is called\t"<<b<<endl;
}
};
Derived class is dependent on Base class.So first compiler intialise the Base class members and then intialise the derived class.
Rule # 2 : Order of Destructor Call
A Base class constructor will always be called before the derived constructor.
Whereas, in case of order of destructor calls it is exactly opposite,
the Base class destructor will be called after Derived class destructor.
Derived class destructor called first and then Base class constructor is called.
Example 1# -> Simple example of order of destructor
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base class Constructor is called\n";
}
~Base()
{
cout<<"Base class destructor Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Derived d1;
return 0;
}
Output:
Base class Constructor is called
Derived Constructor is called
Derived class destructor is called
Base class destructor is called
Example 1# -> with delete Operator
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base class Constructor is called\n";
}
~Base()
{
cout<<"Base class destructor Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Derived *d1 = new Derived();
delete d1;
return 0;
}
Output:
Base class Constructor is called
Derived Constructor is called
Derived class destructor is called
Base class destructor is called
Let's see the below example: >>>>>>>> Why you need virtual destructor
Example 1# -> with Base class pointer having derived class object address
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base class Constructor is called\n";
}
~Base()
{
cout<<"Base class destructor Constructor is called\n";
}
};
class Derived: public Base
{
public:
Derived()
{
cout<<"Derived Constructor is called\n";
}
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
Base class Constructor is called
Derived Constructor is called
Base class destructor is called
>>> derived class destructor never be called, it is memory leak. Then what is the solution.. Solution is only use the Virtual destructor.
6. What is virtual Destructor? Why is required?
Example # With out Virtual at the Base class
#include<iostream>using namespace std;
class Base
{
public:
~Base()
{
cout<<"Base class destructor is called\n";
}
};
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived(); // Upcasting
delete d1;
return 0;
}
Output:
Base class destructor is called
Tip:
Whenever parent class pointer is assigned with derived (child) class object address, then it is called UPCASTING.
In the above example, delete b will only call the Base class
destructor, which is undesirable. Derived
class object is undestructed, because the derived class destructor is never be called. Which leads to memory leak.
Since Base's destructor is not
virtual
and b
is a Base*
pointing to a Derived
object, delete b
has undefined behaviour: How to overcome this kind of issue? Use of Virtual destructor
When ever there is a UPCASTING or Base class pointer assigned with the derived class object address. Then , we should use "Virtual" destructor in the base class to avoid the memory leaks.
or
You need to have virtual destructors in polymorphic base classes. If a class has any virtual function, then it is necessary to have virtual destructor.
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base()
{
cout<<"Base class destructor is called\n";
}
};
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
Derived class destructor is called
Base class destructor is called
Base class destructor is called
Tip:
Virtual destructor is to destruct the resources in a proper order, when
you delete a base class pointer pointing to derived class object.
7. What is Pure virtual Destructor?
Pure virtual Destructor is assigning the virtual base destructor to zero as shown below.
virtual ~Base() = 0
Simple Rule: Whenever you have virtual destructor it is mandate to have it's definition in the Base class to support for the order of destruction (Otherwise you end up with errors)
Base::~Base(){}
Why it is required?
In order to make a class as Abstract class or Interface. Hiding of internal implementation to the User.
What is Abstract class?
An abstract class contains at least one pure
virtual function. You declare a pure virtual function by using a pure
specifier ( = 0 ) in the declaration of a virtual member function in the
class declaration.
Abstract class doesn't create objects.
Example :
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
/tmp/cchlJ6Bu.o: In function `Derived::~Derived()':
virtualdestr.cpp:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev]+0x2b): undefined reference to `Base::~Base()'
virtualdestr.cpp:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev]+0x4e): undefined reference to `Base::~Base()'
virtualdestr.cpp:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev]+0x2b): undefined reference to `Base::~Base()'
virtualdestr.cpp:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev]+0x4e): undefined reference to `Base::~Base()'
Corrected the above Example :
#include<iostream>using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
Base::~Base() // Mandatory
{
cout<<"Base class destructor is called\n";
}
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
Derived class destructor is called
Base class destructor is called
Derived class destructor is called
Base class destructor is called
Let's create object for the Base class. Abstract class can't create objects.
when you tried to create object for abstract class then lead to compilation error.
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
Base::~Base()
{
cout<<"Base class destructor is called\n";
}
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base ob; // Compilation Error
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
Base::~Base()
{
cout<<"Base class destructor is called\n";
}
class Derived: public Base
{
public:
~Derived()
{
cout<<"Derived class destructor is called\n";
}
};
int main()
{
Base ob; // Compilation Error
Base *d1 = new Derived();
delete d1;
return 0;
}
Output:
virtualdestr.cpp: In function ‘int main()’:
virtualdestr.cpp:23:8: error: cannot declare variable ‘ob’ to be of abstract type ‘Base’
Base ob;
^
virtualdestr.cpp:3:7: note: because the following virtual functions are pure within ‘Base’:
class Base
^
virtualdestr.cpp:8:1: note: virtual Base::~Base()
Base::~Base()
virtualdestr.cpp:23:8: error: cannot declare variable ‘ob’ to be of abstract type ‘Base’
Base ob;
^
virtualdestr.cpp:3:7: note: because the following virtual functions are pure within ‘Base’:
class Base
^
virtualdestr.cpp:8:1: note: virtual Base::~Base()
Base::~Base()
8. Explain about the casting operators in C++?
In C/C++ programming, "Typecasting" is used to convert from one data type to another data type.
For example:
short a=6
int b = (int)a;
* These typecasting are used to avoid the compile time warnings and also to convert with the appropriate data type. Generally they are two type of conversion, Implicit and Explicit conversion.
For implicit conversion, there is no need to define any conversion type, compiler itself will does the job.But whereas in Explicit conversion, it is required to specify the respective conversion type.
char *p="muni";
int *p=(char *)p;
There are 4 kinds of typecasting is present in C++, they are
1. static_cast
2. dynamic_cast
3. const_cast
4. reinterpret_cast
syntax:
static_cast<New_Type>(expression)
dynamic_cast<New_Type>(expression)
const_cast<New_Type>(expression)
reinterpret_cast <New_type> (expression)
For example:
short a=6
int b = (int)a;
* These typecasting are used to avoid the compile time warnings and also to convert with the appropriate data type. Generally they are two type of conversion, Implicit and Explicit conversion.
For implicit conversion, there is no need to define any conversion type, compiler itself will does the job.But whereas in Explicit conversion, it is required to specify the respective conversion type.
char *p="muni";
int *p=(char *)p;
There are 4 kinds of typecasting is present in C++, they are
1. static_cast
2. dynamic_cast
3. const_cast
4. reinterpret_cast
syntax:
static_cast<New_Type>(expression)
dynamic_cast<New_Type>(expression)
const_cast<New_Type>(expression)
reinterpret_cast <New_type> (expression)
- It is also called as compile time conversion or compile time check.
- Use static_cast for ordinary type conversions.
- Static_cast used for conversion of non-polymorphic type
- Static_cast can perform conversions between pointers to related classes, not only up-casts (from pointer-to-derived to pointer-to-base), but also down-casts (from pointer-to-base to pointer-to-derived).
- No checks are performed during run time to guarantee that the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe.
- On the other side, it does not incur the overhead of the type-safety checks of dynamic_cast.
- static_cast doesn't return any values.
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
// This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base),
// in the same way as allowed as an implicit conversion.
//Up Casting
b= &d1;
// Upcasting
d= new Derived;
b= d;
return 0;
}
Output #
As in the above example, it does the implicit conversion of up casting.
Example#2 : Down Casting (converting from pointer-to-base to pointer-to-derived) -> It is not safe and it may yield to NULL ptr or Undefined behavior.
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
//Down Casting
d= &ob;
// Down casting
b= new Base;
d= b;
return 0;
}
Output #
In function ‘int main()’:
error: invalid conversion from ‘Base*’ to ‘Derived*’ [-fpermissive]
d= &ob;
^
error: invalid conversion from ‘Base*’ to ‘Derived*’ [-fpermissive]
d= b;
^
-> Then Solution is : Use Static Cast to avoid these errors
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
//Down Casting
d= static_cast<Derived *>(&ob);
// Down casting
b= new Base;
d= static_cast<Derived *>(b);
return 0;
}
Output:
Here if you observe, static_cast doesn't return any value, it is up to the programmer to keep safe.
dynamic_cast :
- It is also called as RTTI or Run time Type Identification or Run time check.
- dynamic_cast is used for pointer and references, In other words "dynamic_cast" used for converting pointers/references within an inheritance hierarchy.
- dynamic_cast is used for conversion of polymorphic types.
- In order to be a polymorphic type, your class must have at least one virtual function. If your classes are not polymorphic types,
- the base-to-derived use of dynamic_cast will not compile.
- There is a run time over head compared to static_cast.
- since the dynamic_cast execute at run time. If the dynamic cast is successful, then returns the returns valid pointer; otherwise it returns NULL.
#include<iostream>
using namespace std;
class Base
{
};
class Derived: public Base
{
};
int main()
{
Base *b, ob;
Derived *d, d1;
//Down Casting
d= dynamic_cast<Derived *>(&ob);
// Down casting
b= new Base;
d= dynamic_cast<Derived *>(b);
return 0;
}
Output:
Compilation Errors: Since the class is not polymorphic.
In function ‘int main()’:
error: cannot dynamic_cast ‘& ob’ (of type ‘class Base*’) to type ‘class Derived*’ (source type is not polymorphic)
d= dynamic_cast<Derived *>(&ob);
^
error: cannot dynamic_cast ‘b’ (of type ‘class Base*’) to type ‘class Derived*’ (source type is not polymorphic)
d= dynamic_cast<Derived *>(b);
^
Example #2 : DownCasting for a polymorphic class (with virtual function in class)
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(){}
};
class Derived: public Base
{
int a;
public:
void fun(){}
};
int main()
{
Base *b, ob;
Derived *d, d1;
// Down casting
d= dynamic_cast<Derived *>(&ob);
// Down casting
b= new Base();
d= dynamic_cast<Derived *>(b);
if(d == NULL)
{
cout<< "NULL"<<endl;
}
return 0;
}
Output:
dynamic_cast.cpp: In function ‘int main()’:
dynamic_cast.cpp:22:33: warning: dynamic_cast of ‘Base ob’ to ‘class Derived*’ can never succeed [enabled by default]
d= dynamic_cast<Derived *>(&ob);
Reason for the compiler warning:
'Base' class don't have any Derived class part. so it cannot be casted.
When you create Base object, it will not have anything which Derived contains and hence when you cast it to derived, the Derived's part will not be there. Also, polymorphism will work with pointers and references.
The compiler will not stop you from doing anything stupid things. It will just warn you
Example #3 : Up casting and Down casting using Dynamic Cast.
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(){}
};
class Derived: public Base
{
};
int main()
{
Base *b, *ob;
Derived *d, *d1;
//Upcasting
d1= new Derived();
ob=dynamic_cast<Base *>(d1);
if(ob == NULL)
cout<< "NULL"<<endl;
else
cout<< "NOT NULL"<<endl;
// Down casting
b= new Base();
d= dynamic_cast<Derived *>(b);
if(d == NULL)
{
cout<< "NULL"<<endl;
}
return 0;
}
Output:
NOT NULL
NULL
Here the dynamic cast operator returns the valid pointer if it is converted properly else it will return zero.The down casting always fail and return the NULL pointer.
const_cast
- const_cast can be used to remove or add const to a variable, no other C++ cast is capable of removing it (not even reinterpret_cast).
- Used to remove the const, volatile, and __unaligned attributes.
- Avoid this unless you are stuck using a const-incorrect API.
#include <iostream>
using namespace std;
void print (int *ctr)
{
cout << *ctr << '\n';
}
int main () {
const int val = 10;
const int *ptr = &val;
print ( const_cast<int *> (ptr) );
return 0;
}Output:
10
Notes : It converts the constant pointer to non constant pointer.
Example #2 : convert the const type to non const using const_cast.
#include <iostream>
using namespace std;
void print (char *ctr)
{
cout << ctr << '\n';
}
int main () {
const char *ptr = "muni";
print ( const_cast<char *> (ptr) );
return 0;
}
Output:
Muni
reinterpret_cast
- reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes.
- The operation result is a simple binary copy of the value from one pointer to the other.
- All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.
- reinterpret_cast for low-level reinterpreting of bit patterns. Use with extreme caution.
#Example 1: If there are two different classes, then try to convert one class pointer type to another class pointer type by using static_cast leads to error.
#include<iostream>
using namespace std;
class X
{
};
class Y
{
};
int main()
{
X *ox;
Y *oy;
ox= new X;
oy= static_cast<Y *>(ox);
return 0;
}
# compile Error: X and Y are unrelated classes and you can't use the static_cast for unrelated classes and it is strictly to be used for related classes.
Example #2 : Convert one pointer type of class to another pointer of class type (But it is not safe).
#include<iostream>
using namespace std;
class X
{
};
class Y
{
};
int main()
{
X *ox;
Y *oy;
ox= new X;
oy= reinterpret_cast<Y *>(ox);
return 0;
}
#Notes:
This code compiles, although it does not make much sense, since oy points to an object of a totally unrelated and likely incompatible class. Dereferencing b is unsafe.
9. Explain about the CONSTANT pointer and pointer to a CONSTANT?
Pointer to constant: The location of pointer can be changed, but the data contained in pointer cannot be changed.
Syntax:
<Data type of pointer> const *<name of pointer>
const <Data type of pointer> *<name of pointer>
Both are same behavior:
e.g:
const char *p - pointer to character constant
char const *p - pointer to constant character
e.g:
const int *p - pointer to Integer constant
int const *p - pointer to constant Integer
Constant Pointer : The location of pointer cannot be changed, but the data contained in the pointer can be changed
<Data type of pointer> * const <name of pointer>
E.g:
char *const p - constant pointer to character
int *const p - constant pointer to Integer
-----------------------------------------------------------------------------------------------------------
> Pointer to constant content
> Pointer to constant content
#Example 1: Pointer to constant content < Pointer to constant integer>
#include<iostream>
int main()
{
int i=4, j=3;
// p is a pointer to constant integer
// or Pointer to a constant integer
const int *p = &i;
// Content of the pointer can't be changed
*p=10 // Not allowed
}
Output:
const_pointer.cpp: In function ‘int main()’:
const_pointer.cpp:10:5: error: assignment of read-only location ‘* p’
*p=10; // Not allowed
--------------------------------------------------------------------------
> constant integer pointer
#include<iostream>
int main()
{
int i=4, j=3;
// p is a pointer to constant integer
// or Pointer to a constant integer
int const *p = &i;
// Content of the pointer can't be changed
*p=10; // Not allowed
return 0;
}
Output:
const_pointer.cpp: In function ‘int main()’:
const_pointer.cpp:10:5: error: assignment of read-only location ‘* p’
*p=10; // Not allowed
>>> Pointer can be changed, but not the content.
-------------------------------------------------------------------------
#include<iostream>
int main()
{
int i=4, j=3;
// p is a pointer to constant integer
// or Pointer to a constant integer
int const *p = &i;
// Content of the pointer be changed
p=&j; // allowed
return 0;
}
------------------------------------------------------------------------------
> Constant Pointer -> Data or content can be changed
#include<iostream>
int main()
{
int i=4, j=3;
// p is a pointer to constant integer
// or Pointer to a constant integer
int *const p = &i;
// Content of the pointer be changed
*p=10; // allowed
return 0;
}
--------------------------------------------------------------------------------
> Constant Pointer -> Data or content can be changed.
But Pointer can't be changed.
#include<iostream>
int main()
{
int i=4, j=3;
// p is a pointer to constant integer
// or Pointer to a constant integer
int *const p = &i;
// Content of the pointer be changed
p=&j; // Not allowed
return 0;
}
-----------------------------------------------------------------------------------
> Pointer to constant and also constant Pointer.
#include<iostream>
int main()
{
int i=4, j=3;
// p is a pointer to constant integer
// or Pointer to a constant integer
const int *const p = &i;
// Content of the pointer be changed
p=&j; // Not allowed
*p=7;
return 0;
}
-----------------------------------------------------------------------------------
#include<iostream>
int main()
{
// p is a pointer to constant character
const char *p = "muni";
char const *q = "sek";
*p='c'; // Not allowed
*q='d'; // Not Allowed
return 0;
}
----------------------------------------------------------------------------------
#include<iostream>
int main()
{
// p is a pointer to constant character
char *const p = "muni";
p=p+1; // Not allowed
return 0;
}
----------------------------------------------------------------------------------
#include<iostream>
int main()
{
// p is a pointer to constant character
char const *p = "muni";
p=p+1; //Allowed
return 0;
}
---------------------------------------------------------------------------
10.What is Static Variable? How the static variables are used in C++? What is Static Function?
Static variables:
One copy of variable is shared across all the objects. (or) Same copy of variable is shared across all the objects.Static variable are accessed using static member function.
Thumb rule:
Static member variable must be initialized outside of the class using '::' scope resolution operator.
Other we will end up with the compiler errors.
<return Type> Classname :: <static variable> = Any value;
e.g: int Base :: static_variable = 0;
Static Member function:
If the static member variables are public, we can access them directly using the class name and the scope resolution operator
What if static member variables are private, how to access them? The answer is using static member functions.
static member variables, static member functions are not attached to any particular object.
It always accessed using class name::<static_variable> or class name::<static_function>
What happens if you don't initialize the static variable?
int Base :: static_variable = 0; You will end up with the unreferenced errors.
Can i intialise the static variable inside class?
C++ ISO forbids to initialize the static variables, but there is provision for const static variables.
class Base
{
public:
static const int var=3;
};
Here you don't need to initialize outside the class.
Example 1: With out static member
#include <iostream>
using namespace std;
class Base
{
public:
int data;
void displayData();
};
void Base ::displayData()
{
cout<<" The object address is:\t"<<this<<"\t and data is :"<<data<<endl;
}
int main()
{
Base obj1, obj2;
obj1.data=20;
obj2.data=30;
obj1.displayData();
obj2.displayData();
return 0;
}
Output:
The object address is: 0xbfa6d6f8 and data is :20
The object address is: 0xbfa6d6fc and data is :30
Observe above: the variable is not shared across the objects.
Thumb rule:
static member variable must be initialized outside of the class using '::' scope resolution operator.
Other we will end up with the compiler errors.
#include <iostream>
using namespace std;
class Base
{
public:
static int data;
static void displayData();
};
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int main()
{
Base::data=20;
Base::data=30;
Base::displayData();
Base::displayData();
return 0;
}
Notes: Static Variables and static function can be accessed only with class name and scope resolution (::), It doesn't have neither any objects nor "this" pointer for static variables and functions.
Output:
/tmp/ccEKEINg.o: In function `Base::displayData()':
singleto.cpp:(.text+0x9): undefined reference to `Base::data'
/tmp/ccEKEINg.o: In function `main':
singleto.cpp:(.text+0x4b): undefined reference to `Base::data'
singleto.cpp:(.text+0x55): undefined reference to `Base::data'
collect2: error: ld returned 1 exit status
"Why compilation Errors":
Static variables are not initialized explicitly as "int Base::data=0".
If you don't declare, will end up with the errors.
#include <iostream>
using namespace std;
class Base
{
public:
static int data;
static void displayData();
};
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int Base :: data=0; // Intialise the static Variables.
int main()
{
Base::data=20;
Base::data=30;
Base::displayData();
Base::displayData();
return 0;
}
Output:
The data is :30
The data is :30
#Example : Const static variable can be initialize inside class.
#include <iostream>
using namespace std;
class Base
{
public:
static const int data = 30; // You can intialise inside class, there is no need explicit.
static void displayData();
};
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int main()
{
Base::displayData();
return 0;
}
Output:
The data is :30
#Example: counter Variable is shared by all Base class objects,
When a new Base object is created, the constructor called and set to the current value of the counter and increments to the next object. This way to generate the unique values for the objects.
#include <iostream>
using namespace std;
class Base
{
static int counter;
int data;
public:
Base()
{
data=counter++;
}
void displayData();
};
int Base::counter=0;
void Base ::displayData()
{
cout<<"The data is :"<<data<<endl;
}
int main()
{
Base ob1, ob2, ob3;
// The static variable is kept in between functional values.
ob1.displayData();
ob2.displayData();
ob3.displayData();
return 0;
}
Output:
The data is :0
The data is :1
The data is :2
Notes: Store the value and then increment for the next object.
#EXAMPLE: VERY IMPORTANT FOR SINGLETON IMPLEMENTATION
#include<iostream>
using namespace std;
int &func();
int &func()
{
static int a;
int *a1=new int;
cout<<"The address of static variable\t:"<<&a<<endl;
cout<<"The address of pointer variable\t:"<<a1<<endl;
cout<<"The value pointed by the pointer\t:"<<*a1<<endl;
a1=&a;
cout<<"The address pointed by the pointer variable\t:"<<&(*a1)<<endl;
return *a1;
}
int main()
{
cout<<"The function address value : First Call\t"<<&func()<<endl;
cout<<"The function address value : Second Call \t"<<&func()<<endl;
cout<<"The function value with out Reference : Third Call \t"<<func()<<endl;
return 0;
}
Output:
The address of static variable :0x804a0d4
The address of pointer variable :0x90cc008
The value pointed by the pointer :0
The address pointed by the pointer variable :0x804a0d4
The function address value : First Call 0x804a0d4
The address of static variable :0x804a0d4
The address of pointer variable :0x90cc018
The value pointed by the pointer :0
The address pointed by the pointer variable :0x804a0d4
The function address value : Second Call 0x804a0d4
The address of static variable :0x804a0d4
The address of pointer variable :0x90cc028
The value pointed by the pointer :0
The address pointed by the pointer variable :0x804a0d4
The function value with out Reference : Third Call 0
Notes:
The static member variable is created once in memory and same memory is used for subsequent calls.
It shall not be created in memory for another function call. The same memory is been used for all function calls.
int &func()
{
static int a;
return a;
}
or
int &func()
{
static int a;
int *p= new int;
p=&a;
return p;
}
q= func() // It returns 0x0
q= &func() // It returns the address (&a or &(*p)) both are same.
11. What is "this" pointer in C++?
this pointer holds the address of the object. "this" pointer is hidden and it is been passed as argument to the non static member functions.
There is no "this" pointer for the static function, since the static variable and static member can't be accessed using objects and It is accessed by using <classname>::<static_variable> or <classname>::<static_function>.
this pointer is hidden argument passed as shown below.
#include<iostream>
using namespace std;
class base
{
int data;
public:
base(int a)
{
data=a;
}
void display()
{
cout<<"The value of data\t"<<data<<endl;
}
};
int main()
{
base ob(2); // *this = &ob contains address of ob
ob.display();
}
Note #1:
This calling function ob.display() having no arguments, but actually it has one.
When compiled, the compiler converts as display(&ob)
Note #2:
void display() is converted by the compiler into:
void display(base* const this) { cout<<"The value of data\t"<<this->data<<endl; }
When we need to call Explicitly "this pointer" ?
When you have a constructor (or member function) that has a parameter with the same name as a member variable, you can differentiate them by using “this”.
#include<iostream>
using namespace std;
class base
{
int data;
public:
base(int data)
{
data=data;
}
void display()
{
cout<<"The value of data\t"<<data<<endl;
}
};
int main()
{
base ob(2);
ob.display();
}
Output:
Compilation shall be sucessful, but the output is undefined value or junk Value.
How to overcome this
-----------------------------
#include<iostream>
using namespace std;
class base
{
int data;
public:
base(int data)
{
this->data=data;
}
void display()
{
cout<<"The value of data\t"<<data<<endl;
}
};
int main()
{
base ob(2);
ob.display();
}
Output:
2.
Notes: In the constructor you can observe, this is been used here.
-------------------------------------------------------
Second USE Case ::: Chaining of the objects.
-------------------------------------------------------
It allow a series of functions to be “chained” together, so several functions can be called on the same object.
e.g: ob.set(2).add(4).display()
Before this please understand the function returning the reference:
-------------------------------------------------------------------
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
this->counter = 0;
}
Base get_copy()
{
return *this;
}
Base& get_copy_as_reference()
{
return *this;
}
Base* get_pointer()
{
return this;
}
void increment_counter()
{
this->counter++;
}
void display()
{
cout << this->counter << endl;
}
private:
int counter;
};
int main()
{
Base ob;
ob.increment_counter();
ob.display();
ob.get_copy().increment_counter();
ob.display();
ob.get_copy_as_reference().increment_counter();
ob.display();
ob.get_pointer()->increment_counter();
ob.display();
return 0;
}
Output:
1
1
2
3
Notes:
From the above example, it is evident that,
Base get_copy()
{
return *this;
}
-> shall Create the New Object or clone of the existing object. Whereas
Base& get_copy_as_reference()
{
return *this;
}
Base* get_pointer()
{
return this;
}
It will return the local object address (Same object address) and it won't create new object. So that's why the output values are 2 and 3.
Reference function return the address of same object to the function (ob.get_copy_as_reference().increment_counter())
How reference been used in chain of function calls?
When a reference to a local object is returned, the returned reference can be used to chain function calls on a single object.
#include <iostream>
using namespace std;
class Base
{
public:
Base &set_data(int j)
{
counter=2;
return *this;
}
Base &add_value(int i)
{
counter +=i;
return *this;
}
void display()
{
cout << counter << endl;
}
private:
int counter;
};
int main()
{
Base ob;
ob.set_data(2).add_value(10).display();
return 0;
}
Output:
12 // Local object address or reference is being returned.
11. What is Association vs Aggregation vs Composition?
Association: ( Uses-a ): is a relationship of objects.Where all objects have their own lifecycle and there is no owner
The relationship may be unidirectional or bidirectional or indirect association, so that the two objects are known each other.
Other words, one class have a relationship with an other class object. e.g.: Foo class uses Bar object
Examples:
> Doctor and Patient:
A doctor can see many patients in a day, and a patient can see many doctors in a day for second opinion. Doctor uses a patient to earn income, patient uses a doctor for health checkup.
> Teacher and student:
Multiple students can associate with single teacher and single student can associate with multiple teachers.
> Engineer Uses a Swipe card
Software Engineer uses a Swipe card to enter the X company office premises.
Important Point is: There is no ownership between the objects and both have their own lifecycle.
Both can be created and deleted independently.
One–to–one Associations
One–to–many Associations
The association is represented by the following symbol in UML:
Example: A Student and a Faculty are having an association.
Unidirectional Relationship
unidirection_assoc.cpp
------------------------------
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class student
{
private:
string m_student_name;
public:
student(string name):m_student_name(name)
{
}
string get_student_name() const
{
return m_student_name;
}
};
class professor
{
private:
/* Association */
// One Professor Many Students 1 to *(many) Association
// 1 to many students
vector<student *> m_students;
string m_professor_name;
public:
professor(string name):m_professor_name(name)
{
}
// Add Students
void add_students(student *st)
{
m_students.push_back(st);
}
void display()
{
unsigned int length = m_students.size();
cout<<"Professor :"<<m_professor_name<<endl;
for (unsigned int count = 0; count < length; ++count)
cout<<m_students[count]->get_student_name()<<' ';
}
};
int main()
{
student *s1= new student ("RAM");
student *s2= new student ("KRISH");
student *s3= new student ("JAY");
professor *p1=new professor ("RISHI");
p1->add_students(s1);
p1->add_students(s2);
p1->add_students(s3);
p1->display();
// No one is the owner
delete s1;
delete s2;
delete s3;
// We can create and destory the objects
// independently.
delete p1;
return 0;
}
Bidirectional Relationship
bidirectional_assoc.cpp
------------------------------
#include<iostream>
#include<string>
#include<vector>
using namespace std;
// Class Forward Declartion
class professor;
class student
{
private:
string m_student_name;
vector<professor *> m_professor;
public:
student(string name):m_student_name(name)
{
}
string get_student_name() const
{
return m_student_name;
}
// Add professsors
void add_professsors(professor *pf)
{
m_professor.push_back(pf);
}
void display_students();
};
class professor
{
private:
/* Association */
// One Professor Many Students 1 to *(many) Association
// many to many students
vector<student *> m_students;
string m_professor_name;
public:
professor(string name):m_professor_name(name)
{
}
// Add Students
void add_students(student *st)
{
m_students.push_back(st);
//Student add the professor
st->add_professsors(this);
}
string get_professor_name() const
{
return m_professor_name;
}
void display()
{
unsigned int length = m_students.size();
cout<<"In Professor class, professor Name :"<<m_professor_name<<endl;
cout<<"Student name :"<<endl;
for (unsigned int count = 0; count < length; ++count)
cout<<m_students[count]->get_student_name()<<' '<<endl;
}
};
void student::display_students()
{
unsigned int length = m_professor.size();
cout<<"In Student class, Student Name :"<<m_student_name<<endl;
cout<<"Professor Name :"<<endl;
for (unsigned int count = 0; count < length; ++count)
cout<<m_professor[count]->get_professor_name()<<' '<<endl;
}
int main()
{
student *s1= new student ("RAM");
student *s2= new student ("KRISH");
student *s3= new student ("JAY");
professor *p1=new professor ("RISHI");
professor *p2=new professor ("DAVID");
professor *p3=new professor ("THOMAS");
p1->add_students(s1);
p1->add_students(s2);
p2->add_students(s1);
p2->add_students(s3);
p3->add_students(s2);
p3->add_students(s3);
p1->display();
p2->display();
p3->display();
cout<<endl;
s1->display_students();
s2->display_students();
s3->display_students();
// No one is the owner
delete s1;
delete s2;
delete s3;
// We can create and destory the objects
// independently.
delete p1;
delete p2;
delete p3;
return 0;
}
Indirect Association Relationship
indirect_assoc.cpp
-------------------------
#include<iostream>
#include<string>
using namespace std;
class Book
{
private:
string book_name;
int book_id;
public:
Book(string name, int id): book_name(name), book_id(id)
{
}
string get_book_name()
{
return book_name;
}
int get_book_id()
{
return book_id;
}
};
class Library
{
private:
static Book book_list[5];
Library();
public:
static Book *get_book(int id)
{
for(int count=0; count <5; count++)
{
if(book_list[count].get_book_id() == id)
return &(book_list[count]);
}
return NULL;
}
};
Book Library::book_list[5]={Book("C++", 1), Book("Java", 2), Book(".NET", 3), Book("C#", 4), Book("OS", 5)};
class User
{
private:
string user_name;
int m_book_id;
public:
User(string name, int id):user_name(name), m_book_id(id)
{
}
int get_book_id()
{
return m_book_id;
}
string get_user_name()
{
return user_name;
}
};
int main()
{
User user_obj("muni", 1);
int book_id= user_obj.get_book_id();
Book *book_obj= Library::get_book(book_id);
cout<<"The Book Name : "<< book_obj->get_book_name()<<endl;
cout<<"The Book Id : "<<book_obj->get_book_id()<<endl;
}
Aggregation (HAS-A Relationship): It is Special form of Association.
A directional association between objects. When an object ‘has-a’ another object, then you have got an aggregation between them. Aggregation is also called a “Has-a” relationship
Where all objects have their own lifecycle but there is ownership and child objects can not belong to another parent object.
Let’s take an example of Department and teacher. A single teacher can not belong to multiple departments, but if we delete the department teacher object will not be destroyed. We can think about it as a “has-a” relationship.
E.g: Employee has a relation ship with the Address.
I have an object which I've borrowed from someone else. When Foo dies, Bar may live on
Aggregation is also referred to as a Weak Association and is represented by the following symbol:
#include<iostream>
#include<string>
using namespace std;
class Address
{
private:
string state;
string city;
string street;
public:
Address(string street, string city, string state)
{
this->street=street;
this->city=city;
this->state=state;
}
string get_street_name(){ return street; }
string get_city_name(){ return city; }
string get_state_name(){ return state; }
};
class Employee
{
private:
string m_employee_name;
Address *m_employee_address;
public:
Employee(string name, Address *address):m_employee_name(name), m_employee_address(address){
}
void print_employee_details()
{
cout<<"Empolyee Name: "<< m_employee_name<<endl;
cout<<"Street name: "<<m_employee_address->get_street_name()<<" "<<"city name :"<<" " \
<<m_employee_address->get_city_name()<<" "<<"State_name :"<<" "<<m_employee_address->get_state_name()<<endl;
}
};
int main()
{
Address *addr_obj= new Address("OHIO DR", "PLANO", "TEXAS");
{
Employee emp_obj("RAM", addr_obj); emp_obj.print_employee_details();
} // Employee goes out of scope, still address object lives on
addr_obj->get_street_name();
addr_obj->get_city_name();
addr_obj->get_state_name();
delete addr_obj;
return 0;
}
Composition (HAS-A Relationship): It is strong type of Aggregation.
It is also called as The Death relationship
In this type of Aggregation the child object does not have their own life cycle. The child object's life depends on the parent's life cycle. Only the parent object has an independent life cycle. If we delete the parent object then the child object(s) will also be deleted.
object composition models a “has-a” relationship between two objects. A car “has-a” Engine. Your computer “has-a” CPU,. Human Body “has-a” heart
e.g.:
For example, the company and company location, a single company has multiple locations.
If we delete the company then all the company locations are automatically deleted.
The company location does not have their independent life cycle, it depends on the company object's life (parent object).
When a body is created, the heart is created too. When a person’s body is destroyed, their heart is destroyed too.
Because of this, composition is sometimes called a “death relationship”. unidirectional relationship, because the body knows about the heart. The UML representation of composition as:
Example: A class contains students. A student cannot exist without a class. There exists composition between class and students. The lifetimes of both the objects are the same
Foo class has a Bar object as data member.
Foo has a Bar object as data member -> Foo contains a Bar. It can't exist without it.
composition and aggregation
Compositions:
> use normal member variables > We Can use pointer values if the composition class automatically handles allocation/deallocation
> Responsible for creation/destruction of parts
Aggregations:
> Typically use pointer or reference members that point to or reference objects that live outside the scope of the aggregate class
> Not responsible for creating/destroying parts
unidirectional_compos.cpp
-----------------------------------
#include<iostream>
#include<string>
using namespace std;
/*
* Book
*/
class Book
{
string book_name;
int book_id;
public:
Book(string name, int id):book_name(name), book_id(id)
{
}
string get_book_name()
{
return book_name;
}
int get_book_id()
{
return book_id;
}
};
/*
* Library
*/
class Library
{
private:
Book m_book;
string m_library_name;
public:
Library(string name, Book book_obj): m_library_name(name), m_book(book_obj)
{
}
void display_library()
{
cout<<"The Library Name :"<< m_library_name<<endl;
cout<<"Book name :"<<m_book.get_book_name()<<endl;
cout<<"Book Id :"<<m_book.get_book_id()<<endl;
}
};
int main()
{
Library lib_ob("PLANO LIBRARY", Book("Devotional", 1233));
lib_ob.display_library();
return 0;
}
With Pointer Composition
-------------------------
#include<iostream>
#include<string>
using namespace std;
/*
* Engine
*/
class Engine
{
string engine_name;
int engine_id;
public:
Engine(string name, int id):engine_name(name), engine_id(id)
{
}
string get_engine_name()
{
return engine_name;
}
int get_engine_id()
{
return engine_id;
}
};
/*
* Car
*/
class Car
{
private:
Engine *m_engine;
string car_name;
public:
Car(string name): car_name(name)
{
m_engine = new Engine("X_POWER", 123);
}
~Car()
{
delete m_engine;
}
void display_car()
{
cout<<"The Car Name :"<< car_name<<endl;
cout<<"Engine name :"<<m_engine->get_engine_name()<<endl;
cout<<"Engine Id :"<<m_engine->get_engine_id()<<endl;
}
};
int main()
{
Car *car_obj= new Car("AUDI");
car_obj->display_car();
delete car_obj;
return 0;
}
House and rooms: If we delete the house, room also shall destroy. This is death Relationship.
Owner, lifetime, and child object:
Association | Aggregation | Composition | |
Owner | No owner | Single owner | Single owner |
Life time | Have their own lifetime | Have their own lifetime | Owner's life time |
Child object | Child objects all are independent | Child objects belong to a single parent | Child objects belong to a single parent |
Generalization:
This implies an "is a" relationship. One class is derived from another, the base class. Generalization is implemented as inheritance in C++. The derived class has more specialization. It may either override the methods of the base, or add new methods.
Change in structure or behavior of a class affects the other related class, then there is a dependency between those two classes. It need not be the same vice-versa. When one class contains the other class it this happens.
Example:
#include<iostream>
#include<string>
using namespace std;
class Wheel
{
string wheel_name;
public:
Wheel(string name)
{
wheel_name=name;
}
string get_wheel()
{
return wheel_name;
}
};
class Car
{
string car_name;
public:
void get_car_wheel(Wheel &wheel_obj)
{
cout<<"The car wheel Type is"<<" "<<wheel_obj.get_wheel();
}
};
int main()
{
Wheel whel_obj("MRF");
Car car_obj;
car_obj.get_car_wheel(whel_obj);
return 0;
}
Realization
Realization is a relationship between the blueprint class and the object containing its respective implementation level details. This object is said to realize the blueprint class.
Realization specifies a contract between two or more types. Where one type (here Interface Imammals) defines the contract and the other type (Cat, Dog) promises to carry out.
Example:
#include<iostream>
using namespace std;
class IMammals{
public:
virtual void walk() = 0;
};
class Cats: public IMammals {
public:
void walk() {
cout<< "Cat is walking" << endl;
}
};
class Dogs: public IMammals {
public:
void walk(){
cout<< "Dog is walking" << endl;
}
};
int main(void) {
Cats aCat;
Dogs aDog;
IMammals *ptrMammals = NULL;
ptrMammals = &aCat;
ptrMammals->walk();
ptrMammals = &aDog;
ptrMammals->walk();
return 0;
}
Using UML, realization is represented by an dotted arrow that points from the type two(Cat,Dog or Contractor) class to the type one class(IMammals or Contractee). The tip of the arrow is an empty triangle. +-----------------+
| IMammals |
|-----------------|
| |
+---------|>| |<|--------+
| +-----------------+ |
| |
| |
+-----+-----+ +-----+-----+
| Cat | | Dog |
|-----------| |-----------|
| | | |
+-----------+ +-----------+
will answer the below questions in another post.
7. Explain about string classes in C++?
8. What are Templates and why they are used?
11. What is Smart pointer in C++ 11 standard?
12. What are design pattern used in C++? Explain some of them?
14. Explain different types of inheritance in C++?
16. What do you mean by reference in C++?
17. What do you need to mention reference operator in C++ function? what are the advantages?
18. What are storage classes in C++?
19. What are access specifiers in C++?
21. Explain about the casting operators in C++?
22. Difference between Volatile vs Register keyword in C++?
23.Is it possible to have virtual constructors in C++?
24.What is STL? Explain the STL operations?
25. Difference between vector vs list?
26. What is memory leak and how to detect the memory leaks in C++?
27. Can we debug macros using GDB? How to debug the macros using GDB?
28. What is difference between macro and inline function? which is efficient?
29. What are the ways of intialise the data members of class?
30. What is Implicit and explicit conversion operator in C++?
32. What is friend function in C++?
33. Template class vs template function in C++?
34. What is list, dequeue in c++?
35. How to connect the database using C++?
36. What is operator overloading in C++?
37. What are the unit testing frameworks used in C++?
38. Explain me the file operations in C++?
39. What is Exception handling and how it is implemented in C++?
Database Questions:
1. Explain stored procedure and how it is implemented in database?
2. What is Normalization?
3. How to drop the table?
4. How to create/delete/update the Table?
5. How to remove particular column in a table?
6. How to insert the values in the Table?
7. How to optimise the database access with respect to application?
8. what is difference between RDMS (SQL) and NOSQL
thanks for sharing this information
ReplyDeletetableau training in bangalore
tableau training in bangalore jayanagar
tableau training in bangalore marathahalli
tableau training in bangalore btm
best tableau training institutes in bangalore
tableau classroom training in bangalore
python training in bangalore
best python training institute in bangalore
Cari beragam peluang penghasilan – selanjutnya anda juga harus bisa mengerti dan mengetahui tentang bagaimana anda bisa mendapatkan keuntungan
ReplyDeleteasikqq
http://dewaqqq.club/
http://sumoqq.today/
interqq
pionpoker
bandar ceme
freebet tanpa deposit
paito warna terlengkap
syair sgp
This is an amazing blog, thank you so much for sharing such valuable information with us.
ReplyDeleteVisit for best logo and brochure designing services at- brochure designer in delhi.
graphic designer in delhi
freelance graphic designer in delhi
freelance graphic designer in delhi ncr
freelance graphic designer in noida
freelance logo designer in delhi
freelance logo designer in delhi ncr
freelance web designer in delhi ncr
freelance website designer in delhi ncr
freelance designer in delhi
freelance website designer in delhi
freelance web designer in delhi
freelance graphic designer services in delhi
freelancer graphic designer services in delhi ncr
freelancer graphic designer services in delhi
freelancer graphic services in delhi ncr
freelancer logo services in delhi
freelancer logo services in delhi ncr
freelancer web designer services in delhi ncr
freelancer web designer services in delhi
freelance web designer services in delhi
freelance website designer services in delhi
freelance website designer services in delhi ncr
freelance logo designer service in delhi
freelance logo designer service in delhi ncr
logo designer in delhi
brochure design in delhi
logo design in delhi
freelance logo design in delhi
freelance logo designer in gurgaon
freelance logo designer in noida
This comment has been removed by the author.
ReplyDeleteThanks for sharing suach an awesome blog.
ReplyDeleteWeb Development Services in Gurgaon.
CRM Service Provider Company in Gurgaon
Wordpress Web Development Service in Gurgaon
Magento Web Development Service in Gurgaon
PHP Web Development Company in Gurgaon.
Nice Post. I like your blog. Thanks for Sharing.
ReplyDeleteLinux training in Noida
Good To Share Information With Us Thanks For Sharing
ReplyDeleteHadoop Training in Hyderabad
Hadoop Course in Hyderabad
Well written articles like yours renews my faith in today's writers. The article is very informative. Thanks for sharing such beautiful information.
ReplyDeleteBest Data Migration tools
Penetration testing companies USA
What is Data Lake
Artificial Intelligence in Banking
What is Data analytics
Big data Companies USA
What is Data Lake
What is Data Migration
What is Data Science
smm panel
ReplyDeletesmm panel
iş ilanları
instagram takipçi satın al
hirdavatciburada.com
beyazesyateknikservisi.com.tr
servis
tiktok jeton hilesi
Good content. You write beautiful things.
ReplyDeletetaksi
mrbahis
sportsbet
sportsbet
korsan taksi
mrbahis
hacklink
vbet
vbet
كيف تبيع أثاثك المستعمل
ReplyDeleteأفضل شركات شراء الأثاث المستعمل
salt likit
ReplyDeletesalt likit
F5D3DR
zonguldak
ReplyDeleteağrı
bakırköy
alanya
aksaray
3S8
tokat
ReplyDeleteankara
trabzon
istanbul
izmir
izmit
kocaeli
56LİBT
çeşme transfer
ReplyDeletesoulmate ajans
bor yağı filtre kağıdı
yağ süzme filtre kağıdı
PGV7