Sie sind auf Seite 1von 36

Constructors

and Destructors
Constructor
 Constructor—what’s this?
 method used for initializing objects (of certain
class)
 a recipe for creating object of a given class

 Constructor—do we need it?


 do the class variables need initialization?
Constructor—declaring
 For the T class:

T(args); or T::T(args);

class point
{
double x, y;
public:
// …
point(double, double); // no return value, even void
point(double); // overloadable
point();
};
Constructor—an unusual method
 We cannot not specify the return value (even:
no void).
 We cannot call it for the already constucted
object.
 We cannot get it’s address.
 It is not even visible in the class scope and has
no name (according to ANSI).
Calling
 Constructor with no args (default constructor):

point p1;

 Others:

point p3(10.0, 20.0); // 2 arg.


point p2(1.0); // 1 arg.
// point p1(); // this would be a call of p1 function

point p2=1.0; // this way 1 arg. c. only


Calling
 we may specify which one to call

point p3=point(10.0, 20.0);


point p2=point(1.0);
point p1=point();

or:

point p3=point::point(10.0, 20.0);


point p3=point::point(1.0);
point p1=point::point();
Calling
 annonymous objects

point pu; // not anonymous object pu


pu = point (3);
// temporary anonymous object,
// it is deleted (right after assignment or
// later, „when not needed anymore”)
point(20);
// temporary anonymous and useless
point * ppu;
ppu=&point();
// an error hard to trace, correct syntax
Defining
class point inline point::point(double d)
{ {
double x, y; x=y=d;
public: }
// …
point(double, double); point::point(double x0,
point(double); double y0)
point() {
{ x=x0;
x=y=0.0; y=y0;
}; }
};
Initialization list
 in a definition of a constructor (exclusivelly here) we may use
the initialization list

T() : member(initializer) [, member(initializer) …] { }

class point
{
double x, y;
public:
// …

point():x(0.0), y(0.0) {};

};
Initialization list
inline point::point(double d)
:x(d), y(d)
{
// all done
}

point::point(double x, double y)
:x(x), y(y) // it is unambiguous !!!
{
// all done
}
Initialization list
 the only way of initializing const and reference
members.
 in i.l. except the class members (declared in the very
class, and not inherited) we may also define the way
of constructing virtual and direct base classes.
 position on the i.l. is of no importance, initialization
is performed in a following order: base classes
(virtual and then direct bases in order of declaration),
member variables in order of declaration,
constructor’s body.
Initialization list
point::point(int x, int y):x(x), y(y) {}; //OK.

inline point::point(int i) :x(i), y(x) {}; //OK.

inline point::point(int i) :y(x), x(i) {}; //OK.

// point::point(int i) :y(i), x(y) {} — oops !!!


The default constructor
 if no constructor was declared, then compiler
generates the default constructor (constructor with no
arguments) of an empty body, for T class:

T::T()
{
}

 if we declare any constructor (even constructor with


args) then compiler does not generate the default
constructor.
Order of constructor calling
 Constructors
1. base class (classes in order of declaration)
2. class members in order of declaration
3. constructor’s body

 Important: object class members (and base classes),


if not initialized in the initialization list, are actually
initialized twice:
1. by the default constructor of their class
2. in the body of constructor of object being created
An example
class segment
{
point p1;
int number;
point p2;
};

segment::segment() // what happens here ???


:p1(1.0, 1.0)
{
p2=point(1.0);
};
An example
class segment
{
point p1;
int number;
point p2;
};

segment::segment()
:p1(1.0, 1.0) // constr. p1 (2-arg), constr. p2 (default)
{ // number not initialized
p2=point(1.0); // constr. temp. (1 arg.), assignmemt
}; // destr. temp.
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);


Compiler generated copy
constructor
 Compiler generates copy constructor if programmer
does not define one (other constructors are not
important in this case).

 Compiler generated copy constructor copies object


field by field
(base classes and object members with their copy constructors
– just like in case of initialization list it works also when
the class has const members)

for the point class:


point(const point & p) :x(p.x), y(p.y) {}
Destructor
 What is the destructor?
 Easy to guess

 When do we need it?


 Even easier
Destructor
 Destructor of the class T:
~T();

 np.:
~point() // no args, no ret. value
{
cout << ”\nit’s me, The Point (x:”
<< x << „ y:” << y;
<< „) in a moment I’ll be The Late Point”;
}
Destructor
 as opposed to constructor it is in the class
scope

 we may call it

 destructor, if not defined by programmer, is


generated by compiler
 it has empty body, but …
Order of calling constructors and
destructors
 Constructors
1. base class (classes in order of declaration)
2. class members in order of declaration
3. constructor’s body

 Destructors – simply opposite order


1. destructor’s body
2. destructors of class members (order opposite to
declaration)
3. destructor of the base class (classes in order opposite to
declaration)
Order of calling constructors and
destructors
 objects defined in blocks (local, automatic)
 constructors are called when the definition is executed
(met)
 destructors after leaving the block, order opposite to
constructors

 global objects (static)


 constructors are called in an order of objects’ definitions,
before calling the main() function
 destructors in order opposite to constructors, after
finishing main().
Order of calling constructors and
destructors
 dynamic objects are controlled by the
programmer (new and delete).

 memory allocation and a constructor call:


when the operator new is executed

 destructor and deallocation: delete


Constructing and destructing
dynamic objects
point *pp0=new point;
point *pp1=new point(1.0);
point *pp2=new point(10.0, 20.0);
point *arrPoints=new point[10];
// array of 10 points
// initialized with the default constructor
// in order of increasing addresses
// new T[] – calls only the default constructor

delete pp1;
delete pp2;
delete pp0;
delete [] arrPoints;
Example
point global=777;
int f(int) { segment o; }

void main() {
point local;
point *p_local;
local=global;
local=point(10,20);
int a=f(1);
for (int i=0; i<2; i++) {
point in_block=local;
}
p_local = new point(1.0);
point local2(10,20);
delete p_local;
p_local = new point();
}
Example
point global=777;
int f(int) { segment o; } c4, c5, d5, d4
c1
void main() {
point local; c2
point *p_local;
local=global;
local=point(10,20); c3, d3
int a=f(1);
for (int i=0; i<2; i++) {
point in_block=local; c6, i==1 c7
} d6, i==1 d7
p_local = new point(1.0); c8
point local2(10,20); c9
delete p_local; d8
p_local = new point(); c10
} d9, d2,
d1, ???10
Example
 define class: person

class person
{
int age;
char *name,
*lastName;
public:
person(const char *name, const char *lastName, const int age);
person(const person & o);
~person();
};
Example
inline person::person(const char *name, const char *lastName, const int age)
:age(age)
{
person::name=new char[strlen(name) + 1];
strcpy(person::name, name);
person::lastName=new char[strlen(lastName) + 1];
strcpy(person::lastName, lastName);
}

inline person::person(const person & o)


:age(o.age), name(new char[strlen(o.name) + 1]),
lastName(new char[strlen(o.lastName) + 1])
{
strcpy(name, o.name);
strcpy(lastName, o.lastName);
}
Example
inline person::~person()
{
delete [] name;
delete [] lastName;
}
Example
 define the queue class (FIFO queue of persons)

class queue
{
person **persons; // array of pointers to persons in queue
const int capacity; // queue capacity
int length; // number of persons currently in queue
public:
queue(int capacity);
~queue();
int insert(const person &o); // 1-no more room, 0-inserted
int collect(person &o); // 1-empty queue, 0-collected
};
Example
queue::queue(int capacity)
:capacity(capacity), length(0),
persons(new (person*) [capacity])
{
}

queue::~queue()
{
for (int i=0; i<length; i++)
delete persons[i]; // elements
delete [] persons; // array
}
Example
int queue::insert(const person &o)
{
if (length==capacity)
return 1;
persons[length++]=new person(o); // copy the method’s arg.
return 0;
}
Example
int queue::collect(person &o)
{
if (length==0)
return 1;

o.~person(); // we do not know (yet)


o=*persons[0]; // how to overload the = operator

length--;
for(int i=0; i<length; i++)
persons[i]=persons[i+1];

return 0;
}
Example
int queue::collect(person &o)
{
if (length==0)
return 1;

o.~person(); // we do not know (yet)


o=*persons[0]; // how to overload the = operator

length--;
for(int i=0; i<length; i++)
persons[i]=persons[i+1];

return 0;
}
// find the memory leak !!!

Das könnte Ihnen auch gefallen