Constructors 1

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 54

Constructors

Copy constructor
• it is for initializing objects using other objects of the
same class, for the T class:

T::T(const T &);

• parameter has to be a reference (otherwise temp.


object would be created, that should also be
somehow initialized – with the copy constructor!)
• parameter should be const to permit to call the
constructor with the const argument
Copy constructor
• for example. c.c. of the point class:

point(const point & p) :x(p.x), y(p.y) {}

• as a copy constructor for class T we may use


other constructor that may be called with one
argument of type &T:

point(const point &, int=7);


E.g
class Point◦
{◦
public: ◦
Point(const Point& p); // copy Constructor◦
Point::Point(const Point&p)◦
{◦
x = p.x;◦
y = p.y; ◦
} . . .◦
Point p(53); // calls default constructor◦
Point s = p; // calls copy constructor.◦
Point q(p) // calls copy constructor.◦
Program
#include<iostream>
class Point
{ private:
int x, y;
public:
Point(int x1, int y1)
{ x = x1; y = y1; }
// Copy constructor
Point(const Point &p2)
{ x = p2.x; y = p2.y; }
int getX()
{ return x; }
int getY()
{ return y; } };
int main()
{
Point p1(10, 15); //Normal constructor is called here
Point p2 = p1; // Copy constructor is called here
// Let us access values assigned by constructors
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
return 0;
}
• If we don’t define our own copy constructor, the
C++ compiler creates a default copy constructor
for each class which does a member wise copy
between objects. The compiler created copy
constructor works fine in general. We need to
define our own copy constructor only if an object
has pointers or any run time allocation
Copy Constructors
• Shallow Copy:
– The data members of one object are copied into the data
members of another object without taking any dynamic
memory pointed to by those data members into
consideration. (“memberwise copy”)
• Deep Copy:
– Any dynamic memory pointed to by the data members is
duplicated and the contents of that memory is copied
(via copy constructors and assignment operators -- when
overloaded)
• Using a copy constructor we simply copy the data values member by
member. This method of copying is called shallow copy. If the object is a
simple class, comprised of built in types and no pointers this would be
acceptable. This function would use the values and the objects and its
behavior would not be altered with a shallow copy, only the addresses
of pointers that are members are copied and not the value the address
is pointing to. The data values of the object would then be inadvertently
altered by the function. When the function goes out of scope, the copy
of the object with all its data is popped off the stack.
• If the object has any pointers a deep copy needs to be executed. With
the deep copy of an object, memory is allocated for the object in free
store and the elements pointed to are copied. A deep copy is used for
objects that are returned from a function.
Copy Constructors
• In every class, the compiler automatically supplies both a
copy constructor and an assignment operator if we don't
explicitly provide them.
• Both of these member functions perform copy operations by
performing a memberwise copy from one object to another.
• In situations where pointers are not members of a class,
memberwise copy is an adequate operation for copying
objects.
• However, it is not adequate when data members point to
memory dynamically allocated within the class.
class CopyConstructor
{
char *s_copy;
public:
CopyConstructor(const char *str)
{
s_copy = new char[16]; //Dynamic memory allocation
strcpy(s_copy, str);
} /* concatenate method */
void concatenate(const char *str)
{
strcat(s_copy, str); //Concatenating two strings } /* copy constructor */
~CopyConstructor ()
{
delete [] s_copy;
}
void display() Shallow copy
{
cout<<s_copy<<endl;
}
};
int main()
{
CopyConstructor c1("Copy");
CopyConstructor c2 = c1; //copy constructor
Copy
c1.display(); Copy
c2.display(); CopyConstructor
c1.concatenate("Constructor"); //c1 is invoking CopyConstructor
concatenate()
c1.display();
c2.display();
return 0;
}
class CopyConstructor
{ char *s_copy; Deep copy
public:
CopyConstructor (const char *str)
{ s_copy = new char[16]; //Dynamic memory allocation
strcpy(s_copy, str);
}
CopyConstructor (const CopyConstructor &str)
{ s_copy = new char[16]; //Dynamic memory allocation
strcpy(s_copy, str.s_copy);
}
void concatenate(const char *str)
{ strcat(s_copy, str); //Concatenating two strings }
~CopyConstructor() { delete [] s_copy; }
void display() { cout<<s_copy<<endl; } };
int main()
{ CopyConstructor c1("Copy");
CopyConstructor c2 = c1; //copy constructor
c1.display();
c2.display();
c1.concatenate("Constructor");
c1.display();
c2.display(); Copy
Copy
CopyConstructor
return 0; } Copy
class String{
Deep copy
private:
char *s;
int size;
public:
String(const char *str = NULL);
~String()
{ delete [] s; }
String(const String&);
void print()
{ cout << s << endl; }
void change(const char *);
};
String::String(const char *str)
{ size = strlen(str);
s = new char[size+1];
strcpy(s, str);}
void String::change(const char *str)
{ delete [] s;
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}
String::String(const String& old_str)
{ size = old_str.size;
s = new char[size+1];
strcpy(s, old_str.s);}
int main()
{ String str1("welcome");
String str2 = str1;
str1.print(); // what is printed ? str2.print();
str2.change("changing"); str1.print(); // what is
printed now ? str2.print(); return 0;
}

welcome
welcome
welcome
changing
class String
{ Shallow copy
private:
char *s;
int size;
public:
String(const char *str = NULL); // constructor
~String()
{ delete [] s; }// destructor
void print() { cout << s << endl; }
void change(const char *); // Function to change
};

String::String(const char *str)


{
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}
void String::change(const char *str)
{
delete [] s;
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
} same
int main() same
{ distinct
String str1(“same"); distinct
String str2 = str1;

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


str2.print();

str2.change(“distinct ");

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


str2.print();
}
Memory Layout
Memory space
• The memory space is allocated to the data members of a class only
when an object of the class is declared, and not when the data
members are declared inside the class. Since a single data member can
have different values for different objects at the same time, every
object declared for the class has an individual copy of all the data
members.
• On the other hand, the memory space for the member functions is
allocated only once when the class is defined. In other words, there is
only a single copy of each member function, which is shared among all
the objects. For instance, the three objects, namely, book1, book2 and
book3 of the class book have individual copies of the data members
title and price. However, there is only one copy of the member
functions getdata () and putdata () that is shared by all the three
objects
Static Data Member
• A type of data member that is shared among all objects of class is
known as static data member.
• The static data member is defined in the class with static keyword.
• When a data member is defined as static, only one variable is created
in the memory even if there are many objects of that class.
• A static data item is useful when all objects of the same class must
share a common item of information.
• The characteristics of a static data member are same as normal static
variable.
Static Data Member
• It is visible only in the class, in which it is defined but its lifetime
• Starts when the program starts its execution.
• Ends when the entire program is terminated.
• It is normally used to share some data among all objects of a particular
class.
• The main difference between normal data member and static data
member is that
• each object has its own variable of normal data member.
• On the other hand, static data member is shared among all objects of the class.
• Only one memory location is created for static data member that is shared
among all objects.
Uses of Static Class Data
• Why would you want to use static member data?
• As an example, suppose an object needed to know how many other
objects of its class were in the program.
• for example :
• In a road-racing game, a race car might want to know how many other cars
are still in the race.
• In this case a static variable count could be included as a member of
the class. All the objects would have access to this variable.
• It would be the same variable for all of them; they would all see the
same count.
Separate Declaration and Definition
• Static member data requires an unusual format.
• Ordinary variables are usually declared and defined in the same
statement.
• Static member data, on the other hand, requires two separate
statements.
• The variable’s declaration appears in the class definition, but the
• Variable is defined outside the class, in much the same way as a global
variable.
• Why is this two-part approach used?
• If static member data were defined inside the class, it would violate the idea
that a class definition is only a blueprint and does not set aside any memory.
Separate Declaration and Definition
• Putting the definition of static member data outside the class also
serves to emphasize that
• the memory space for such data is allocated only once, before the program
starts to execute, and that
• one static member variable is accessed by an entire class; each object does
not have its own version of the variable, as it would with ordinary member
data.
• In this way a static member variable is more like a global variable.
Write a program that counts the number of
objects created of a particular class (1/2)
class yahoo
{
private:
static int n;
public:
yahoo()
{ n++; }
void show()
{
cout<<“you have created ”<<n<<“ objects so far ”<<endl;
}
};
Write a program that counts the number of
objects created of a particular class (2/2)
int yahoo::n=0;
void main()
{
yahoo x,y;
x.show(); OUTPUT:
yahoo z; • You have created 2 objects so far.
x.show(); • You have created 3 objects so far.
}
• Private Static Data members
• Access Rules for Static Data members
Test:public_in=12; ok
Test:private_in=12; Error

• Static Member function


Uses only static data members only.
Classname::membername or
Objectname. membername
#include <iostream>
using namespace std;
class test
{ int code;
static int count;public:
void setcode(void)
{ code = ++count; }
void showcode(void)
{ cout << "object number :" << code << "\n";
}
static void showcount(void)
{ cout << "count:" << count << "\n"; }};
int test::count;int main()
{test t1, t2;
t1.setcode();
t2.setcode();
test::showcount();
test t3;
t3.setcode();
test::showcount();
t1.showcode();
t2.showcode();
t3.showcode(); return 0;}
Constant Variables

If you make any variable as constant, using const


keyword, you cannot change its value. Also,
the constant variables must be initialized
while they are declared.

int main
• { const int i = 10; const int j = i + 10; // works
fine i++; // this leads to Compile time error }
class St
{
public:
int i;
St(int x) // constructor
{
i = x;
}

int fal() const // constant function


{ // can do anything but will not modify any data members
cout << "welcome";
}
int add()
{
i++;
}
};
int main()
{
St objOne(10); // non const object
const St objTwo(20); // const object

objOne.fal(); // No error
objTwo.fal(); // No error

cout << objOne.i << objTwo.i;

objOne.add(); // No error
// objTwo.add(); // Compile time error
}

Here, we can see, that const member function never changes data members of
class, and it can be used with both const and non-const objecta. But a const
object cannot be used with a member function which tries to change its data
members.
class Zee
{ int i; mutable int j;
public: Zee() { i = 0; j = 0; } mutable keyword
void fool() const
{ i++; // will give error
j++; // works, because j is mutable } };
int main() { const Zee obj; obj.fool(); }

mutable keyword is used with member variables of class, which we want to change
even if the object is of const type. Hence, mutable data members of
a const objects can be modified.
Friends of Classes

• A friend function of a class is a function that is not a member of a class,


but has access to the private members of the class.
• A friend function is declared with the keyword friend.

friend <return type><function name>(<parameter type list>);

• Using friend functions is a way of breaking the rule of encapsulation. As


such, friend functions should only be used when absolutely necessary.
• A Friend function can be friend of many classes
• A friend function has no object reference and do not have the this
pointer

36
Properties of friend function

• It can't be called using object like other member function.


• It is called like normal functions in C or C++.
• Private member can be accessed inside friend function using object
name and dot(.) operator.
• It can take multiple objects as parameter as required.
• It should be declared in all the classes whose objects are sent as
parameter.
• It can be declared or defined in private, public or protected section
of a class.
• It is not mutual by default.
class base
{
int val1,val2;
public:
void getdata()
{
cout<<"Enter value 1: ";
cin>>val1;
cout<<"Enter value 2: ";
cin>>val2;
}
friend float mean (base obj);
};
float mean(base obj)
{
return float(obj.val1 + obj.val2)/2;
}
void main()
{
base obj;
obj.getdata();
cout<<"Mean value is: "<<mean(obj);
}
Same friend function of two classes
class B;
class A
{ private:
int numA;
public: A(): numA(12) { } // friend function declaration
friend int add(A, B);
};
class B
{ private:
int numB;
public: B(): numB(1) { } // friend function declaration
friend int add(A , B);
};
int add(A objectA, B objectB)
{ return (objectA.numA + objectB.numB);
} int main()
{ A objectA;
B objectB;
cout<<"Sum: "<< add(objectA, objectB); return 0;
}
Friend classes

• As mentioned before, it is possible to make an entire class a friend of


another class.
• When a class is declared as a friend of another class every member
function of the friend class is a friend function to the other class.

If we make the entire class as a friend the automatically all the member functions
of the class become friends. For class B to be a friend of class A.
The class A must explicitly declare class B is its friend in the public section

41
• class A
{
friend class B;

};

class B
{

};
class A
{
private:
int a,b;
public:
A()
{
a=10;
b=20;
}
friend class B;
};
class B
{
public:
B()
void showA(A obj)
{
cout<<”The value of a: ”<<obj.a<<endl;
}
void showB(A obj)
{
cout<<”The value of b: ”<<obj.b<<endl;
}};
main()
{
A x;
B y;
y.showA(x);
y.showB(x);}
Class friend to a specified class Member
Return an object from the function
class Complex
{
private:
int real;
int imag;
public: Complex(): real(0), imag(0) { }
void readData()
{ cout << "Enter real and imaginary number
respectively:"<<endl;
cin >> real >> imag; }
Complex addComplexNumbers(Complex comp2)
{
Complex temp;

temp.real = real+comp2.real;

temp.imag = imag+comp2.imag;
return temp; }
void displayData()
{
cout << "Sum = " << real << "+" << imag << "i"; }};
int main()
{ Complex c1, c2, c3;
c1.readData();
c2.readData();
c3 = c1.addComplexNumbers(c2);
c3.displayData();
return 0;
}
This pointer
• The ‘this’ pointer is passed as a hidden
argument to all nonstatic member function
calls and is available as a local variable within
the body of all nonstatic functions. ‘this’
pointer is a pointer that holds the memory
address of the current object.
• Member function of every object has access
to a pointer “this”.
class Test
{
private:
int x;
public:
void setX (int x)
{ this->x = x;}
void print()
{ cout << "x = " << x << endl; }};
int main()
{
Test obj;
int x = 20;
obj.setX(x);
obj.print();
return 0;}
To return reference to the calling
object
class Test
{
private:int x;
int y;
public:Test(int x = 0, int y = 0)
{ this->x = x;
this->y = y;
}Test &setX(int a)
{ x = a; return *this;
}
Test &setY(int b)
{ y = b; return *this;
}
void print()
{ cout << "x = " << x << " y = " << y << endl; }};
• int main()
• {Test obj1(5, 5);
• obj1.setX(10).setY(20);
• obj1.print();return 0;}

You might also like