Copyright Hannu Laine C++-programming Part 3 Hannu Laine.

22
Copyright Hannu Laine C++-programming Part 3 Hannu Laine

Transcript of Copyright Hannu Laine C++-programming Part 3 Hannu Laine.

Page 1: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

Copyright Hannu Laine

C++-programmingPart 3

Hannu Laine

Page 2: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 2

Constructors

Constructors are used to initialise objects.

Writing proper default constructor for a class

guaranties that we never have undefined

contents in objects.

Constructors are called automatically, when space is

allocated for objects (immediately after space

allocation).

This means that constructors are called

1) when object is declared.

2) when object is passed as a value parameter.

3) when space for an object is allocated from dynamic

memory using new operator.

The name of constructor function is same than class

name.

Another advantage of constructor (with parameters) is

that it makes object initialisation easy with

values according the class user’s will.

Page 3: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 3

First example of the class constructor

In the following examples we assume, that the class

definition is as follows:

class Person {

public:

Person(); //default constructor

Person(const char *name0, int age0);

void print();

private:

char name[30];

int age;

};

Page 4: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 4

Simple constructor (default constructor)Constructor without parameters is called default

constructor.

It is invoked by default, when we declare an object in simple way like Person person;

1. Prototype in class definition:

Person();

2. Implementation:Person::Person() {

strcpy(name, "");age = 0;

}

3. How it is used:

Person p1, p2;

It is now guaranteed, that both objects p1 and

p2 have initialised data members name(empty string) and age (0).

4. How it works internally:You can think that declaration

Person person;means two phase operation

1) Space allocation for object person.2) Performing constructor function for that

objectlike calling person.Person();

Remark 1. Remember that f() in C++ is same than f(void) in C.

Remark 2. It is not correct to declare Person person();

Page 5: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 5

Constructor with parameters

Default constructor guaranties that all objects have initialised member values (member values are not undefined).

Constructors with parameters provide a programmer an easy method to initialise object members with values according his/her will.

1. Prototype in the class definition:

Person(const char *name0, int age0);

2. Implementation:Person::Person(const char *name0, int

age0) {strcpy(name, name0);age = age0;

}

3. How it is used:

Person person("Matti", 20);

person.print();

Again internally this is two-phase operation, where memory space is allocated for an object and after that constructor function is called.

Remark 1. Note that a class can contain (and usually it does) both the default constructor and constructor with parameter. This is possible because of function overloading.

Page 6: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 6

Using default parametersWe can “combine” two functions (constructor without parameters and constructor with parameters) using default parameters of C++. Constructor for the class Person:1. The prototype of the constructor in the class

definition:Person(const char *name0 = ””, int age0=0);

2. The implementation of the constructor function isstill the same as on the previous page.

3. Then it is possible to construct person objects in the following ways:

1. Person person1;2. Person person2(”Matti”);3. Person person3(”Matti”, 20);

Another more general example of default parameters://function prototypevoid f (int a, double b=0.0, const char *c = “abc”); //function implementationvoid f (int a, double b, const char *c ) {

//do something with parameters}

Function f can be called in the following ways: 1) f(3);2) f(10, 2.5);3) f(10, 13.2, ”opqrstu”);

The default values of parameters are indicated only in function prototype.

Page 7: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 7

Using default parameters it is possible instead of two separate constructors

Person(); Person(const char *name0, int age0);

to write only one

Person(const char *name0="", int age0=0); The implementation of this constructor is still as simple

as before: Person::Person(const char *name0, int age0){

strcpy(name,name0);age = age0;

}

Now our class definition becomes more simple:

class Person {

public:

Person(const char *name0="", int age0=0);

void print();

private:

char name[30];

int age;

};

Using default parameters

Page 8: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 8

The two advantages of constructors were:1. We never have undefined contents in objects. 2. It makes object initialisation easy.

These advantages are valid also for dynamic objects because new operator calls constructor after allocation.

Example.//we now allocate person objects// from dynamic memoryint main (void) {

Person *p1;Person *p2;Person *p3;p1 = new Person; // Default constr. is calledp2 = new Person("Matti");p3 = new Person("Matti", 20);

p1->print();…delete p1;delete p2;delete p3;return 0;

}

This also works for dynamic objects

Page 9: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 9

Copy constructorsWhen it is used:1) Programmer can use copy constructor explicitly to

create an object that is a copy of an existing object (see page 10, item 3).

2) Compiler generates a call to copy constructor, when object is passed as a value parameter (see page 10, item 4).

By default, the compiler generates a copy constructor for each class. This default copy constructor makes a copy of an object member by member.

If a class has dynamic data members this copy constructor generated by the compiler is not adequate as we will see soon. Then the programmer needs to write a proper copy constructor.

We use reference parameter in the copy constructor. We have learned reference parameter concept earlier.

In our first example the class has no dynamic member, but it is used as a simple example to illustrate the basics of copy constructor.

Page 10: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 10

Example class with copy constructor

We use the following class to illustrate copy

constructor:

class Person {public:

Person(const char *name0="", int age0=0);

Person(const Person &p); //copy constructor

void print();private:

char name[30];int age;

};

Page 11: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

11

Copy constructor1. Prototype in the class definition:

Person(const Person &p);

2. Implementation:Person::Person(const Person &p) {

strcpy(name, p.name);age = p.age;

}

3. How it is used explicitly:Person person("Matti", 20);Person twinBrother(person);

4. How it is used implicitly:void f(Person p);void main(void) {

Person person(“Matti”, 20);f(person);

}void f(Person p) {

//do what ever with parameter p}

When function f is called and parameter object p is allocated from the stack, copy constructor is used to make it identical to object person.

Page 12: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 12

A) Class with no dynamic data members:

Constructors can be used to initialise data

members to valid values automatically so that

objects never have undefined contents.

Constructors with parameters make initialisation

easy with values according the class user’s will.

Destructors often have no useful function.

B) Class with dynamic data members

In addition to what was said in A constructors can

be used to allocate space for dynamic data

members.

Destructors can be used to automatically release

the space of dynamic data members when object

itself is deleted from memory.

Advantages of constructors and destructors

Page 13: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 13

Our example class is now defined as follows:class Person {

public:Person(const char * name0=“”, int

age0=0);void print();

private:char *name; //dynamic data memberint age;

};

Now the data member name is only a pointer. It cannot store the characters of the name. We still want to make that class easy to use. That’s why we allocate the memory space for name string “automatically” in the constructor.

The implementation of the constructor is now:

Person::Person(const char *name0, int age0){name = new char[strlen(name0) + 1];strcpy(name,name0);

age = age0;}

The memory allocation is now OK, but now we can have a new problem. This problem is a so-called memory leak problem. See next page.

Class with dynamic data member

Page 14: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 14

Example of a memory leak:

//class definition from the previous page is herevoid f();void main() {

for (int i = 0, i < 100 ; i++) f();

}

void f() {char name[30];

generate_name(name);Person p(name, 20);p.print();

}Where does this program leak memory and why?How much does it leak memory?

Destructors are needed when a class has dynamic data members to avoid memory leaks. The class definition is now:

class Person {public:

Person(const char * name0=“”, int age0=0);

~Person(); //destructorvoid print();

private:char *name; //dynamic data memberint age;

};

Memory leak problem

Page 15: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 15

Destructors

Destructor is a “complement” of constructor.

The name of the destructor function is ~classname. For example, the destructor of class Person is ~Person.

Destructor function is called automatically just before the object is deleted from memory.

1. Prototype in class definition:

~Person();

2. Implementation:

Person::~Person() {

delete name;

}

3. When it is used:

Destructor is called just before object is deleted

from the memory.Example 1.

void f() { Person person(“Matti”, 20); …}

Example 2.

void f(Person p) { … }

Constructor is called

Destructor is called

Copy constructor is

called

Destructor is called

Page 16: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 16

Destructors We have used destructor to avoid memory leak problem.

But this again generates a new problem. The following example illustrates this:

void main () {Person person(“Matti”, 20); //constr. is

calledf(person);person.print(); //the output is undefined

} //destructor is called

void f(Person p) { //copy constructor is called …

} //destructor is calledIf we don’t have a proper copy constructor the output in the main function is undefined, because destructor that is called at the end of the function f has deleted the name of object person!!

The copy constructor that solves this problem

Person::Person(const Person &p){name = new char[strlen(p.name) + 1];strcpy(name, p.name);

age = p.age;}

Page 17: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 17

Dynamic objects

Constructors are also called when objects are allocated with new operator.

Destructors are called when objects are deleted with delete operator.

Example 3.void f() { Person *pperson; pperson = new Person(“Matti”, 20); … delete pperson; }

The new operator allocates space for Person object. When memory space has been allocated new operator calls constructor. The new operator in the constructor allocates memory for the name member.

When delete operator is called for pperson the delete operator calls destructor of the Person class. In that destructor delete operator is called that deletes the name member from the dynamic memory. After that the "original" delete deletes the person object.

Constructor is called

Destructor is called

Page 18: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 18

The word static is used as opposite to dynamic in the following text. It is not same than keyword static.

We can distinguish four different cases:1. Object in ”static memory” with static members.2. Object in dynamic memory with static members.3. Object in static memory with dynamic member.4. Object in dynamic memory with dynamic

members.

Using class declaration class Person {

public: Person(const char *name0="", int

age0=0); void print(); private: char name[30]; int age;

};

we can demonstrate the first two situations.

1. Object in ”static memory” with static members.

void f() { Person p1(“Maija, 21);…

}

Objects/members in dynamic memory 1/3

p1

Static memory Dynamic memory

name

age

Maija\

0 21

Page 19: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 19

2. Object in dynamic memory with static members.

void f() {Person *p2 = new Person (“Maija, 21);…

delete p2;

}

Objects/members in dynamic memory 2/3

Using class declaration

class Person { public: Person(const char *name0="", int

age0=0);~Person();

void print(); private: char *name; int age;

};

we can demonstrate the last two situations.

3. Object in static memory with dynamic member.void f() {Person p3(“Maija, 21); …}

name

age

Maija\

0 21

p2

Static memory Dynamic memory

Static memory Dynamic memory

Maija\0nameage 21

p3

Page 20: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 20

4. Object in dynamic memory with dynamic members.

void f() {Person *p4 = new Person (“Maija, 21);…

delete p4;

}

Objects/members in dynamic memory 3/3

p4Static memory Dynamic memory

nameage 21

Maija\0

Next we concentrate especially to this last situation to learn how and when memory is allocated to these dynamic memory areas.

We also learn how and why and when these areas are deleted from memory.

Page 21: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 21

Here is the class definition again. We now see the implementations of constructor and destructor too.

//Class definitionclass Person { public: Person(const char *name0="", int age0=0); ~Person(); void print(); private: char *name; int age;};

// Implementations of constructor and destructorPerson::Person(const char *name0, int age0){

name = new char[strlen(name0) + 1];strcpy(name,name0);

age = age0;}

Person::~Person(){delete name;

}

Objects in dynamic memory containing dynamic data members

Page 22: Copyright  Hannu Laine C++-programming Part 3 Hannu Laine.

HL 22

And the small application as a whole:

//Application

void main (void) {

Person *p = new Person(”Maija", 21);

p->print();

delete p;

}

Objects in dynamic memory containing dynamic data members

Program execution explained step by step:

1. Operator new in main function allocates space for a person object from dynamic memory.

2. When that space is allocated, constructor is called for that object. new operator in constructor function allocates space for the name from the dynamic memory and initializes the data members of a person object as well as the char array in dynamic memory.

3. Personal data is displayed on the screen.

4. Delete operator first calls the destructor of the Person class. The delete operator in the destructor releases the character array from the dynamic memory.

5. Finally the delete operator (of main function) releases the person object from dynamic memory.