Level:4 Expert

Welcome back,
This is the continuation of our Cpp Quick reference – From Novice to Expert.
Lets get inside Level 4
LEVEL : 4 | EXPERT
66. Public Inheritance in C++ _ Object Oriented Programming
#include<iostream>
using namespace std;
/*public inheritance*/
class Base{
private:
/*CANT be inherited*/
int restricted;
protected:
/*can be inherited,available as protected member in derived class*/
int id;
public:
/*can be inherited,available as public member in derived class*/
void setid(int iid){
id=iid;};
};
class Derived:public Base{/*public inheritance*/
public:
void disp(){
cout<<id<<endl; //id- is inherited as protected member by derived class*/
}
};
int main()
{
Derived d;
//d.id=786;/*ERROR: trying to access protected member,outside class */
d.setid(123);
d.disp();
return 0;
}
NOTE: class Derived:public Base{} <- public inheritance ,access specifier affects behaviour of base class members in derived class.
In public inheritance, public & protected member of BASE class acts as public & protected member of DERIVED class respectively
67. Protected Inheritance in C++ _ Object Oriented Programming :
#include<iostream>
using namespace std;
/*protected inheritance*/
class Base{
private:
/*CANT be inherited*/
int restricted;
protected:
/*can be inherited,available as protected member in derived class*/
int id;
public:
/*can be inherited,available as PROTECTED member in derived class(THOUGH ITS PUBLIC MEMBER IN BASE CLASS)*/
void setid(int iid){
id=iid;};
};
class Derived:protected Base{/*protected inheritance*/
public:
void via(int x){
setid(x);}
void disp(){
cout<<id<<endl; //id- is inherited as protected member by derived class*/
}
};
int main()
{
Derived d;
//d.setid(123);/*ERROR: trying to access protected member,outside class */
/*SINCE public member setid() of base class has become PROTECTED member of derived class, it CANT be accessed OUTSIDE class */
d.via(786);
d.disp();
return 0;
}
NOTE : In protected inheritance, BOTH public & protected member of BASE class acts as PROTECTED member of DERIVED class.
68. Private Inheritance in C++ :
#include<iostream>
using namespace std;
/*PRIVATE INHERITANCE*/
class Base{
private:
/*CANT BE INHERITED*/
protected:/*can be inherited,available as PRIVATE member in derived class*/
int id;
public:/*can be inherited,available as PRIVATE member in derived class*/
void setid(int iid){
id=iid;}
};
class Derived:private Base{/*private inheritance*/
public:
void disp(){
cout<<id<<endl;}
};
/*both protected & public members has become PRIVATE members of DERIVED class,
so its not available for ANY DERIVED CLASS & OUTSIDE CLASS*/
class Der2:public Derived{
public:
void setnum(int iid){
setid(iid);/*generates ERROR,since setid(PRIVATE MEMBER)*/
id=iid;/*generates ERROR,since id(PRIVATE MEMBER),not avilable for any derived class*/
}
};
int main()
{
Der2 d;
d.setnum(123);/*since private members cant access id(private)*/
d.disp();
return 0;
}
The above program generates ERROR.
Solution for the above issue : Create one more (PUBLIC) function in Derived class, from Der2 class via that public function access member of base class. Flow goes from step1 to step 4, in the below code snippet.
#include<iostream>
using namespace std;
/*PRIVATE INHERITANCE*/
class Base{
private:
/*CANT BE INHERITED*/
protected:/*acts as PRIVATE member in derived class*/
int id;
public:/*acts as PRIVATE member in derived class*/
void setid(int iid){/*4th--> (setid) member ftn set value of id*/
id=iid;}
};
class Derived:private Base{/*private inheritance*/
public:
void d1_id(int iid){/*3rd-->(d1_id) member ftn calls (setid) member ftn*/
setid(iid);
}
void disp(){
cout<<id<<endl;}
};
class Der2:public Derived{
public:
void d2_id(int iid){/*2nd-->(d2_id) member ftn calls (d1_id) member ftn*/
d1_id(iid);
}
};
int main()
{
Der2 d;
d.d2_id(786);/*1st-->derived2 object calls (d2_id) member ftn*/
d.disp();/*since disp()is public ftn it can be called outside class*/
return 0;
}
69. Changing Access Level of Base Class Members in Derived Class :
USING ACCESS DECLARATION
/*USING ACCESS DECLARATION*/
#include<iostream>
using namespace std;
class Base{
protected:
int id;
public:
void setid(int iid){
id=iid;}
};
/*Access declaration changes the ACCESS LEVEL/SCOPE
of base class member in derived class */
/* syntax:
accessDeclaration: say, public/protected/private
BaseclassName :: memberName */
class Derived:private Base{
public: //ACCESS DECLARATION
Base::id; /*now id(PRIVATE member) has become PUBLIC,it can be accessed OUTSIDE CLASS */
void disp(){
cout<<id<<endl;}
};
int main()
{
Derived d;
d.id=123;/*private member is changed scope as public and used OUTSIDE class */
d.disp();
return 0;
}
70. Order of Execution of Constructors and Destructors in Inheritance :
#include<iostream>
using namespace std;
class Base{
public:
Base(){
cout<<"1st-->base class constructor called"<<endl;
}
~Base(){
cout<<"4th-->base class destructor called"<<endl;
}
};
class Derived:public Base{
public:
Derived(){
cout<<"2nd-->Derived class constructor called"<<endl;
}
~Derived(){
cout<<"3rd-->Derived class destructor called"<<endl;
}
};
int main()
{
Derived ob;/*derived class object created*/
return 0;
}
71. C++ Multiple Inheritance :
#include<iostream>
using namespace std;
class Device{
public:
Device(){
cout<<"inherited from Device class"<<endl;
}
int id;
/*void setid(int iid){ //we can do through this method also
id=iid;}*/
};
class Wless{
public:
Wless(){
cout<<"inherited from Wless class"<<endl;}
int model;
/*void setmodel(int mno){ //we can do through this method also
model=mno;}*/
};
class Btooth:public Device,public Wless{
public:
Btooth(){
cout<<"Multiple inheritance"<<endl;}
void setid_model(int iid,int imodel){
id=iid;
model=imodel;
/*setid(iid); //we can do through this method also
setmodel(imodel);*/
}
void thisp()
{
cout<<id<<" "<<model<<endl;}
};
int main()
{
Btooth bt;
bt.setid_model(123,1100);
bt.disp();
return 0;
}
72.a Calling and Passing Values to Base Class Constructor in Derived Class :
#include<iostream>
using namespace std;
class Base{
protected:
int id;
public:
Base(int iid){
id=iid;
cout<<"base class constructor called"<<endl;}
};
class Derived:public Base{
public:
Derived(int x):Base(x){ /*value passed to base class constructor*/
cout<<"derived class constructor called"<<endl;}
void disp(){
cout<<id<<endl;}
};
int main()
{
Derived d(123);
d.disp();
return 0;
}
72.b Calling and Passing Values to Base Class Constructor in Derived Class :
Alternate way
#include<iostream>
using namespace std;
class Base{
protected:
int id;
public:
Base(){
cout<<"base class constructor called "<<endl;}
};
class Derived :public Base{
public:
Derived(int x):Base(){ /*base class constructor can be called*/
id=x; /*and value can be passed*/
cout<<"derived class constructor called"<<endl;}
void disp(){
cout<<id<<endl;
}
};
int main()
{
Derived d(111);
d.disp();
return 0;
}
73. C++ Overriding Base Class Methods in Derived Class :
#include<iostream>
using namespace std;
class Base{
public:
void disp(){
cout<<"base class method called"<<endl;}
};
class Derived: public Base{
public:
void disp(){ /*base class method overridden,i.e., same return type, same ftn.name, same parameters*/
cout<<"derived class method is called"<<endl;
cout<<"which has overridden base class method"<<endl;}
};
int main(){
Derived d;
d.disp();
return 0;
}
NOTE: base class method is overridden by derived class method, when derived class object calls d method, base class method is hidden and derived class method is executed.
74.a Accessing the overridden Methods :
#include<iostream>
using namespace std;
class Base{
public:
void disp(){
cout<<"base class method called "<<endl;}
};
class Derived: public Base{
public:
void disp(){ //base class method overridden
cout<<"derived class method called"<<endl;}
};
int main()
{
Derived d;
d.disp(); //derived class method called
d.Base::disp(); //overridden base class method called
return 0;
}
NOTE: to access overridden method, use SCOPE RESOLUTION OPERATOR
syntax: DerClassObject.BaseClassName :: methodName()
if accessing through derived class object, use DOT OPERATOR & SCOPE RESOLUTION OPERATOR or BaseclassName :: methodName
74.b Accessing the overridden Methods :
#include<iostream>
using namespace std;
class Base{
public:
void disp(){
cout<<"base class method called"<<endl;}
};
class Derived : public Base{
public:
void disp(){ /*inside derived class method, we can call base class overridden METHOD*/
cout<<"derived class method called"<<endl;
Base::disp(); //calls overridden base class method
}
};
int main()
{
Derived d;
d.disp();
return 0;
}
75. C++ this Keyword _ Pointer :
#we get GARBAGE VALUE as output -expected error- solution is provided below
#include<iostream>
using namespace std;
class Device{
public:
int id;
void setid(int id){
id=id;/*puts garbage value,since local variable id is same as member variable id*/
}
void disp(){
cout<<id<<endl;}
};
int main()
{
Device d;
d.setid(123);
d.disp();//prints GARBAGE VALUE
return 0;
}
On executing the above program we get GARBAGE VALUE as output, since local variable is same as member variable. Solution is provided below.
Solution for the above issue (use “this” pointer)
#include<iostream>
using namespace std;
class Device{
public:
int id;
void setid(int id){
this->id=id; /*this pointer points to the member variable, of invoking object*/
}
void disp(){
cout<<id<<endl;}
};
int main()
{
Device d;
d.setid(123);
d.disp(); /*prints correct value, since we used THIS POINTER*/
return 0;
}
NOTE: Every object of a class has an pointer pointing to its own memory address called THIS POINTER
this pointer is available only for the MEMBER FUNCTIONS, It may be used to refer the INVOKING OBJECT
NOT available for FRIEND FTN, since they are not member function of the class.
76.a Calling Methods Using Base Class Type :
/*Calling Methods Using Base Class Type*/
#include<iostream>
using namespace std;
class Base{
public:
void disp(){
cout<<"base class method called "<<endl;}
};
class Derived:public Base{
public:
void disp(){
cout<<"derived class method called"<<endl;}
};
void intro(Base ob){ /*method takes BASE CLASS OBJECT as a parameter*/
ob.disp();
}
int main()
{
Derived d;
d.disp();
intro(d); /*passed derived class method,but calls base class method*/
return 0;
}
76.b Calling Methods Using Base Class Type : using pointer
/*Calling Methods Using Base Class Type*/
#include<iostream>
using namespace std;
class Base{
public:
void disp(){
cout<<"base class method called "<<endl;}
};
class Derived:public Base{
public:
void disp(){
cout<<"derived class method called"<<endl;}
};
void intro(Base *ob){ /*method takes BASE CLASS POINTER as a parameter*/
ob->disp(); /*USE ARROW OPERATOR, since accesing thru' pointer*/
}
int main()
{
Derived d;
d.disp();
intro(&d); /*address is passed*/
return 0;
}
76.c Calling Methods Using Base Class Type : pass by REFERENCE
/*Calling Methods Using Base Class Type*/
#include<iostream>
using namespace std;
class Base{
public:
void disp(){
cout<<"base class method called "<<endl;}
};
class Derived:public Base{
public:
void disp(){
cout<<"derived class method called"<<endl;}
};
void intro(Base &ob){/*PASS BY REFERENCE*/
ob.disp();/*USE DOT OPERATOR, since accesing through OBJECT*/
}
int main()
{
Derived d;
d.disp();
intro(d); /*OBJECT is passed*/
return 0;
}
77. Run Time Polymorphism in C++ and Virtual Functions _ Methods :
RUN TIME POLYMORHISM
Virtual Functions are used to support Run time Polymorphism. When the virtual function is called by using a Base Class Pointer, the Compiler decides at Runtime which version of the function i.e. Base Class version or the overridden Derived Class version is to be called. This is called Run time Polymorphism.
i.e., In Run time polymorphism call to a member function , cause different function to be executed, based on the type of object invoking the function i.e., function works in different forms
Polymorphism occurs when there is a hierarchy of classes and they are related by inheritance
The keyword virtual informs compiler not to call that function, when its overridden, and we know usually base class method is overridden by derived class methods.
NOTE: if the base class method is not overridden, call through derived class OBJECT calls base class method
#include<iostream>
using namespace std;
class Person{
public:
virtual void display(){
cout<<"hi person"<<endl;
}
};
class student : public Person{
public:
void display(){
cout<<"hi student"<<endl;
}
};
class Farmer : public Person{
public:
void display(){
cout<<"hi farmer"<<endl;
}
};
void whosThis(Person &p){ /* LOOK CLOSER: pass by reference-base class reference (Person &p) */
p.display();
}
int main()
{
student anil;
Farmer muthu;
whosThis(anil);
whosThis(muthu);
return 0;
}
78. Virtual Function _ Inherited Attributes, Hierarchical Nature :
Important Note: no matter how many times virtual ftn is inherited, it remains virtual
#include<iostream>
using namespace std;
class Person{
public:
virtual void display(){ //virtual function
cout<<"hi from person"<<endl;
}
};
class student : public Person{ //inherit from base class person
public:
void display(){ //overridden the base class method
cout<<"hi from student"<<endl;
}
};
class Gstudent : public student{ /#Important:*virtual nature is inherited*///inherit from derived class student
public:
/*void display(){ /* $ commented to demostrate hierarchial nature*/
cout<<"hi from Graduate student"<<endl; //overridden the base class method
}*/
};
//call a method by passing the base class parameter, by reference
void whosThis(Person &p){
p.display();
}
int main()
{
Person AuthorRS; //base class object
student bamu; //derived class object
Gstudent randomGuy; //derived class object, inherited from another Derivedclass
whosThis(AuthorRS);
whosThis(bamu);
whosThis(randomGuy); /*calls the method from class student,since no overridden method by that class, demonstrates “hierarchial nature “ $ */
return 0;
}
79. C++ Pure Virtual Functions, Abstract Classes :
Attention pls: when a virtual ftn is not redefined by derived class , version defined by base class is used. If any derived class redefinition is there, that will be used.
However in many situation there can be no meaningful definition of a virtual ftn within the base class.
For eg., in some cases base class may not be able to define an object sufficiently to allow a base class virtual ftn to be created OR if we want all derived class to override a base class ftn.
In such cases use PURE VIRTUAL FUNCTION.
An example of when pure virtual functions are necessary
For example, let’s say that you have a base class called Figure. The Figure class has a function called draw. And, other classes like Circle and Square derive from the Figure class. In the Figure class, it doesn’t make sense to actually provide a definition for the draw function, because of the simple and obvious fact that a “Figure” has no specific shape. It is simply meant to act as a base class. Of course, in the Circle and Square classes it would be obvious what should happen in the draw function – they should just draw out either a Circle or Square (respectively) on the page. But, in the Figure class it makes no sense to provide a definition for the draw function. And this is exactly when a pure virtual function should be used – the draw function in the Figure class should be a pure virtual function.
#include<iostream>
using namespace std;
class Person{ //ABSTRACT CLASS,since contains one or more PURE VIRTUAL FUNCTION
public:
virtual void display()=0; //pure virtual function [syntax: virtual return_type ftn_name(parameters, if any)=0;]
};
//to define the method, use SCOPE RESOLUTION OPERATOR [syntax: return_type BASEclass_name::method_name(){body of the ftn;}]
void Person ::display(){
cout<<"hi from person"<<endl;
}
class student: public Person{ //this SHOULD override the base class method
public:
virtual void display(){
cout<<"hi from student"<<endl;
//if u want dat base class method 2 be called , use SCOPE RESOLUTION OPERATOR
Person::display();
}
};
int main()
{
//Person AuthorRS; error:object cant be created for an ABSTRACT CLASS
student bamu;
bamu.display();
return 0;
}
80. Diamond problem in OOPS, Solution using Virtual Inheritance with Example:
DIAMOND PROBLEM– when there is an inheritance hierarchy containing 2 or more base classes that inherit from a common base, this results in a need of ambiguity resolution in the ABSENCE OF VIRTUAL INHERITANCE
#Demonstrating the issue -error: ambiguous access (solution is provided below)
class Animal{
public:
void walk(){
cout<<"Animal walks"<<endl;
}
};
class Lion : public Animal{
};
class Tiger : public Animal{
};
class Liger : public Lion, public Tiger{
};
int main()
{
Liger diamond;
diamond.walk(); //error C2385: ambiguous access of 'walk'
return 0;
}
SOLUTION for diamond problem, use VIRTUAL INHERITANCE
#include<iostream>
using namespace std;
//SOLUTION for diamond problem, use VIRTUAL INHERITANCE
class Animal{
public:
void walk(){
cout<<"Animal walks"<<endl;
}
};
class Lion : virtual public Animal{ //virtual inheritance
};
class Tiger : virtual public Animal{ //virtual inheritance
};
class Liger : public Lion, public Tiger{ /* virtual inheritance provides only one instance of the common base class*/
};
int main()
{
Liger diamond;
diamond.walk(); //calls base class method, since VIRTUALLY INHERITED
return 0;
}
NOTE: its recommended to use virtual inheritance , when we want to use a derived class as a base class to another derived class <= pls read it again : )
DEMONSTRATING constructor call order:
#include<iostream>
using namespace std;
//constructor call order
class Animal{
public:
Animal(){ //base class constructor
cout<<"base class constructor called"<<endl;
}
void walk(){
cout<<"Animal walks"<<endl;
}
};
class Lion : virtual public Animal{ //virtual inheritance
public:
Lion(){ //derived_1a class constructor
cout<<"derived_1 class constructor called"<<endl;
}
};
class Tiger : virtual public Animal{ //virtual inheritance
public:
Tiger(){ //derived_1b class constructor
cout<<"derived_1b class constructor called"<<endl;
}
};
class Liger : public Lion, public Tiger{
public:
Liger(){ //derived_2 class constructor
cout<<"derived_2 class constructor called"<<endl;
}
};
int main()
{
Liger diamond;
diamond.walk(); //calls base class method, since VIRTUALLY INHERITED
return 0;
}
EXPECTED OUTPUT:
output:
base class constructor called
derived_1 class constructor called
derived_1b class constructor called
derived_2 class constructor called
Animal walks
Press any key to continue . . .
81. Nested Classes or Inner classes :
#include<iostream>
#include<string>
using namespace std;
class Person{
public:
string name;
class Address{ //Nested class
public:
int hno;
string stName;
string place;
};
Address addr; //object of the inner class Address
//method to call the properties
void Locate(){
cout<<name<<endl<<addr.hno<<endl<<addr.stName<<endl<<addr.place<<endl;
}
};
int main()
{
Person AuthorRS;
AuthorRS.name="AuthorRS";
//AuthorRS.hno=18; //error ,since diff scope
AuthorRS.addr.hno=18;
AuthorRS.addr.stName="DummyStrt";
AuthorRS.addr.place="DummyPlace";
AuthorRS.Locate();
//Address ad; object creation //error, since its nested class
//using SCOPE RESOLUTION OPERATOR, can create object for the nested class
Person::Address ad; //initialize if u want
return 0;
}
82. Local Classes in C++ :
#include<iostream>
#include<string>
using namespace std;
void studentList(); //function prototype
int main()
{
studentList(); //function call
return 0;
}
void studentList(){
class student{ //local class
public:
string name;
int age;
void display(){ //method to access the properties
cout<<name<<endl<<age<<endl;
}
};
student bamu; //object
bamu.name="bamu";
bamu.age=18;
bamu.display();
}
83. C++ Operator Overloading Introduction ‘+Operator’ :
#include<iostream>
using namespace std;
class Mk{
public:
int intmk;
int extmk;
Mk(){ //default constructor
intmk=0;
extmk=0;}
Mk(int im,int em){
intmk=im;
extmk=em;}
void disp(){
cout<<intmk<<endl<<extmk<<endl;}
/*operator overloading function*/
Mk operator + (Mk m){ /*here only one parameter is passed, current object parameter is passed implicitly*/
Mk temp;
temp.intmk=intmk+m.intmk; /*here only one parameter is passed, current object parameter is passed implicitly, i.e., m.intmk is passed and current obj intmk is passed automatically*/
temp.extmk=extmk+m.extmk;
return temp;
}
};
int main()
{
Mk m1(10,20),m2(40,70);
Mk m3=m1+m2;
m3.disp();
return 0;
}
NOTE: operator overloading ftn can do any custom operation and return any type, based on the requirement of the program.
syntax: return_type operator + (parameter )
84. Overloading ‘- Operator’ Defining Operator Function outside Class definition :
#include<iostream>
using namespace std;
class Mark{
public:
int intmk;
int extmk;
Mark(){//default constructor
intmk=0;
extmk=0;}
Mark(int im,int em){ //user defined constructor
intmk=im;
extmk=em;}
void disp(){
cout<<intmk<<endl<<extmk<<endl;}
Mark operator-(Mark m); //DECLARATION
};
Mark Mark:: operator-(Mark m)//Defined outside class
{
Mark temp;
temp.intmk=intmk-m.intmk; /*first obj passed automatically,since its a member of class*/
temp.extmk=extmk-m.extmk;
return temp;
}
int main()
{
Mark m1(10,20),m2(40,60);
Mark m3=m2-m1; /*two operands, 1-passed automatically,2-passed manually*/
m3.disp();
return 0;
}
NOTE: here, Mark Mark:: operator-(Mark m)
Mark->return type, Mark:: ->Class to whch it belongs (scope resolution),since the ftn is defined outside class, Mark m –> passing object as parameter[here we pass only one parameter, since the ftn is a member of the class ]
i.e., current object or the object which calls the operator ftn is passed implicitly
85. Overloading Short Hand Operators _ Operator Function as Friend Function :
#include<iostream>
using namespace std;
class Mark{
public:
int mk;
Mark(){
mk=0;}
Mark(int im){
mk=im;}
void disp(){
cout<<mk<<endl;}
friend void operator+=(Mark &curobj,int);/*friend ftn*/
};
void operator+=(Mark &curobj,int bonusmark){
curobj.mk+=bonusmark;}
int main()
{
Mark m(150);
m+=10;
m.disp();
return 0;
}
NOTE: friend ftn doesn’t have THIS POINTER therefore current object will not be passed implicitly, so we have to pass the current object manually.
Syntax:
{
inside class definition..
friend return_type keywordoperator +(curobj.par1,par2); //ftn DECLARATION
};
outside class definition..
return_type keywordoperator +(curobj.par1,par2) {//ftn DEFINITION
curobj.par1+par2;
}
ATTENTION: we pass 2 parameters manually
86. Overloading Increment and Decrement Operators in Prefix form :
#include<iostream>
using namespace std;
class Mark{
public:
int mk;
Mark(){
mk=0;}
Mark(int im){
mk=im;}
void disp(){
cout<<mk<<endl;}
void operator++() {/*no parameter passed,since its an UNARY OPERATOR*/
mk+=3;
}
friend void operator--(Mark &); /*friend ftn doesnt belong to class, so pass current object*/
};
void operator--(Mark &curobj){ /*friend ftn definition, outside class*/
curobj.mk-=5;
}
int main()
{
Mark m1(100);
// m1++;
++m1;
m1.disp();
--m1;
m1.disp();
return 0;
}
87. Introduction to Exception Handling _ try, catch and throw :
Demonstrating Exception occurrence:
/*Exception occurs*/
#include<iostream>
using namespace std;
int main()
{
int a=10,b=0,c;
c=a/b; //exception occurs
cout<<c<<endl;
return 0;
}
To handle the exception use try, throw, catch as follows:
/*to handle the exception use try,throw,catch*/
#include<iostream>
using namespace std;
int main()
{
int a=10,b=0,c;
try{ //place the code block,which may give exception
if(b==0)
throw("Divide by zero error"); //if exception occurs throw exception
c=a/b; //exception occurs
cout<<c<<endl;
}
catch(const char *e){ //handle d exception case
cout<<"Exception occured: "<<e<<endl;
}
return 0;
}
if exception occurs, ‘throw‘ block throws exception to ‘catch‘ block then codes next to ‘throw‘ block will not be executed,.
i.e., control will be passed to ‘catch‘ block.
88. Copy Constructor with Example :
‘Copy Constructor‘ is nothing but a overloaded constructor, it is called when we copy an object to another Or when an object is passed as an argument to an function Or when we return an object from a function. Usually same memory will be shared between the objects, so change in one object get reflected in other, to avoid this use copy constructor and get separate memory.
#include<iostream>
#include<string>
using namespace std;
class Device{
protected:
string *name;
int *id;
public:
Device(string iname,int iid){
name=new string (iname);
id=new int(iid);
}
//copy constructor
Device (const Device &d){ /*pass object by ref and const: value of passed object not changed*/
cout<<"copy constructor called"<<endl;
name=new string (*d.name); //value at d.name
id=new int (*d.id); //value at d.id, since they are pointers
}
void disp(){
cout<<*name<<" "<<*id<<endl; //remember value at
}
void changeVal(string newname,int newid){
*name=newname; //remember value at
*id=newid;
}
};
int main()
{
Device d("awd",123);
Device e=d; //copy constructor called now
d.disp();
e.disp();
d.changeVal("new",786);
d.disp();
e.disp();
return 0;
}
89. Deep Copy and Shallow Copy :
Constructor : Its a special function called when object of class is created. Ideally a constructor must contain the logic to initialize the data members of the class.
Copy Constructor: It is called when an object is initialized at the time of creation. There exist more scenario when an copy constructor is called.
Operator function: C++ allows to overload operator with the help of operator keyword. This helps us to treat user defined types as basic types.
Default copy constructor and =operator function are inserted by compiler, incase they are missing from the class. It performs a bit pattern copy i.e. simply copies data members of one object into another object.
#include<iostream>
using namespace std;
/*default constructor and default copy constructor
are inserted by compiler, when it is missing from a class */
class A{
private:
int x; //data member
public:
A():x(0){ //default constructor
}
void getX(){
cout<<x<<endl;
}
};
int main(){
A obj1; //default constructor called
A obj2=obj1; //default copy constructor is called
obj1.getX(); //0
obj2.getX(); //0
A obj3; //default constructor is called
obj3=obj1; /default =operator ftn is called
obj3.getX(); //0
return 0;
}
/* The above code will work as expected until the class member is not allocated any resource (file or memory). */
The above code will work as expected until the class member is not allocated any resource (file or memory)
Note: Default Constructor and default Copy Constructor are inserted by compiler, when it is missing from a class
when we allocate memory, as below the default copy constructor and overloaded = operator function will copy the pointers and value of N of one object to another object. Which will lead to memory leak and dangling reference issues.
Because of the shallow copy (copying data members irrespective of their types) which is by default.
#include<iostream>
using namespace std;
class A{
private:
int *x;
int N;
public:
A():x(NULL){ //default constructor
}
void allocateX(int N){
this->N=N;
x=new int [this->N]; //dyn.mem.alloc
}
void getX(){
cout<<*x<<endl;
}
~A(){ //destructor
delete []x; //dealloc
}
};
int main(){
A obj1; //default constructor is called
obj1.allocateX(10);
obj1.getX();
A obj2=obj1; //default copy constructor is called
obj2.getX();
A obj3; //default constructor is called
obj3=obj1; //default =operator ftn is called
obj3.getX();
return 0;
}
to overcome the above issues, use DEEP COPY
#include<iostream>
using namespace std;
class A{
private:
int *x;
int N;
public:
A():x(NULL){ //default constructor
}
//copy constructor with deep copy
A(const A &ob){
this->N=ob.N;
this->x=new int [this->N]; //x
}
//= operator with deep copy
void operator=(const A & ob){
this->N=ob.N;
this->x=new int [this->N];
}
void allocateX(int N){
this->N=N;
this->x=new int[this->N];
}
void getX(){
cout<<x<<endl; //*x or return x
}
~A(){ //destructor
delete []x; //dealloc
}
};
int main(){
A obj1; //default constructor is called
obj1.allocateX(10);
obj1.getX();
A obj2=obj1; //deep copying copy constructor is called
obj2.getX();
A obj3; //default constructor is called
obj3=obj1; //deep copy =operator ftn is called
obj3.getX();
return 0;
}
By this we come to the end of this level. If you feel I missed any topic, please let me know, I will try to cover them as well, hopefully.
Corrections and Improvement Suggestions are highly appreciated. Thanks in advance..
love,
<R.S>
For Complete Sourcecode visit my Github Repo
RS-codes

One thought on “CPP QuickReference – From Novice to Expert- Level4”