Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated...

Post on 24-Dec-2015

248 views 7 download

Transcript of Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated...

Constructors and Destructors

OutlineConstructors and Destructors

Default and compiler-generated Overloading Member initialization vs. assignment Initializing const, reference and static members Copy constructor Assignment operator Constructors as type conversion operators Destructors

Declaring and initializing simple variables

When variables of native types are declared there is no question about how much memory to allocate

Initialization is the process of storing a value in newly declared variables

Initializing simple variables

int counter = 0;

char* owner = NULL;

char name[] = “C++”;

double coef[3] = { 0, 1.2, 3.0 };

Initializing class objects

Classes are complex (derived) types They may have many components Example: Employee class has

name, address, id, etc.

Declaration of a variable that is a class (instantiating an object) requires the ‘construction’ of an object by setting aside the required blocks of memory.

Initializing objects

Constructors are special class methods that create an object of that class they have the same name as their class Example: Class Employee

{ public: Employee() {}; // default constructor

What constructors do

Have same name as the classAre called automatically when class

object declaredInitialize (non-static) members

Employee() { id = 0; } Allocate memory for dynamic members

Employee() { char* nameptr = new char[20];}

Allocate any needed resources

Date class in C++class Date {

public: // services

Date();

unsigned getMonth();

void incrDay();

unsigned getDOW();

// more services...

private: // state

unsigned year, day, month;

}

Constructors for the Date class

default - all decisions are made for youDate today;

initializing - you set basic parametersDate today(9,20,1999);

copy - creates an object that is a copy of another objectDate monday(today);

Constructors for the Date classclass Date {

public:

// default constructor

Date();

// explicitly specifying m,d,y

Date(unsigned m, unsigned d, unsigned y);

// copy constructor

Date(const Date& _date);

// parsing a string MM/DD/YYYY

Date(const string& DateStr);

When do constructors get called?Block local (automatic) objectDynamically allocated objectClass argument passed by valueClass object returned by valueClass member that is an objectArray elementTemporary objectLocal static objectGlobal object

Local object

{

Date today; // constructor

// implicitly called

} // destructor implicitly // called here

Dynamic object

{

pstr = new string(“5113”);

...

delete pstr; // destructor called

...

}

Default constructor

Takes no arguments, orAll arguments have default values

Date::Date() {…}

Date::Date(unsigned m = 0, unsigned d = 0, unsigned y = 0) { … }

Date::Date() constructor

Date::Date () {

time_t clock = time(0);

struct tm* tmptr = localtime(&clock);

month = tm_month;

day = tmptr->tm_day;

year = 1900 + tmptr->tm_year;

}

Default constructor (cont.)

Called when object declared without any arguments

Date d;

string s;

Compiler-generated constructor

What if we do not supply any constructor for a class?

Compiler generates one with an empty body

Date() {};

No data members initializedDo not rely on compiler-generated

constructors

Disabling a default constructor

Default constructors do not make sense for some classes classes with no reasonable defaults

class BankAccount { ... };

BankAccount ba; // nameless account?

Disabling a default constructor (cont).Solution: make a default constructor private

BankAccount {

...

private:

BankAccount();

}

Prevents compiler from supplying oneBankAccount ba; // will not compile

Constructing arrays of objects

A default constructor is needed user- or compiler-supplied

Complex cmplarr[10];

Date datearr[20];

There is no way to call constructors with arguments (non-default) for array members

Arrays of objects and non-default constructors

Trick: declare a pointer to an array of objectsAllocate and initialize each object in a loop

Date* dates[31];

for (int day = 0; day < 31; ++day) {

dates[i] = new Date(9, day, 1999);

}

Multiple constructors

What if you wanted your program to be able to create Date objects in a variety of formats? Date today(9,20,1999); Date today(“Sept.,20, 1999”); Date today(9,20,1999), same_as_today;

same_as_today(today);To do this we must have different

versions of the Date constructor.

Overloading constructors

Multiple ways to initialize a Date objects from Month, Day, Year from a date string in a known format from another Date object …

Overloaded constructors different signatures (types and numbers of

arguments)

Calling overloaded constructorsDate today; // default constructor

// explicitly specify m, d, y

Date fdc(12, 31, 2000);

// initialize date from string

Date eoq(“12/12/1998”);

// from another date object

Date eoq2(eoq);

Common tasks of overloaded constructors

Checking argumentsIncrementing the number of

instancesAll Date constructors could call a

private class method to verify input and assign values to private data members

Date::assign(month, day, year)

Date::assign method

Date::Date () {

// initialize struct tm* tmptr...

// assign checks its arguments

assign(tmptr->tm_month,

tmptr->tm_mday,

1900 + tmptr->tm_year);

}

Date::assign method

Date::Date (constr string DateStr) {

// parse m, d, y from DateStr...

// assign checks its arguments

assign(m, d, y);

}

Date::assign methodvoid Date::assign(unsigned _month,unsigned _day, unsigned _year) {

setMonth(_month);

setDay(_day);

setYear(_year);

// counter of Dates instantiated

numCreated++;

}

Direct assignment from the constructor

Rather than calling a private ‘assign’ function, the constructor could do the assignment itself.

Advantage of using ‘assign’ is the isolation of the verification process to that function.

Assignment vs. initialization in constructors

Assignment in the constructor body

Date::Date(unsigned m, unsigned d, unsigned y) {

month = m;

day = d;

year = y;

}

Assignment vs. initialization in constructors

Initialization in the initialization list

Date::Date(unsigned m, unsigned d, unsigned y) :

month(m), day(d), year(y) {};

Empty function body

Initialization list

Assignment vs. initialization in constructors

class Student {

private:

string name;

public:

Student(string aName) { name = aName; };

...

Why initialization is preferred to assignment

When a Student object is constructed, a default constructor for string name is called

Student(string aName) { string name = aName };

this allocates (1 byte of) memory inside Student::Student body, string assignment

operator is called memory is freed and allocated again

A better way of initialization

Uses initializationAvoids allocation, deallocation,

reallocation for name

Student(string aName) : name(aName) {};

Problem: Order of initialization

Initialization takes place in the order that variables were declared

Not the order in which members are in the initialization list!

Subtle dependencies possible which could cause problems (next slide)

Pitfalls of initialization listsclass my_string {

private:

char* rep;

unsigned len;

public:

my_string(const char* cp) :

len(strlen(cp)),

rep(new char[len+1]) {};Member len initialized after repBut rep uses len...

Initializing const and ref members

Assignment to constants and references prohibited

Initialization required

Const and reference members must be initialized in the constructor initialization lists

Initializing static and global objects

Few reasons to have global objectsInitialized in the order of declarationDependencies between global

objects in different filesIf you must, make them local staticInitialized when control thread first

passes over

Copy constructor

Initializes a new object from another, existing one

Signature: Class::Class(const Class&);

Copy constructor for class Date

Date::Date(const Date& date) {

// no need to check passed date arg

month = date.month;

day = date.day;

year = date.year;

}

Uses of the copy constructor

Implicitly called in 3 situations defining a new object from an existing

object passing an object by value returning an object by value

Copy constructor: defining a new object

Date eosem(“12/20/1999”);

// init 2 local objects from eosem

Date eosem2(eosem);// pass by value

Date eosem3 = eosem;// return value

// init a dynamic object from eosem

Date pdate = new Date(eosem);

Copy constructor: passing objects by value

//copy ctor called for each value arg

unsigned dateDiff(Date d1, Date d2);

...

Date today;

Date eosem(12, 20, 1999);

cout << dateDiff(eosem, today);

Avoiding copy constructors

To avoid unnecessarily calling copy constructors

Do not pass object by value; pass by const ref

unsigned dateDiff(const Date& d1, const Date& d2);

Compiler-supplied copy constructor

Copies members bitwiseOK for built-in typesProblematic for resources owned by

objectSlack bytes problem

Compiler-supplied copy constructor: problems

class Date {

char* charRep; // owned by Date

...

Date today;

Date today2(today);

m:9 d:20 y:1999

charRep*

today2

m:9 d:20 y:1999

charRep*

today

9/20/1999

Shallow copy by default

The problem with the compiler supplied copy constructor is that it is a shallow copy constructor.

In the last example, both today and today2 consist of pointers set to the same block of memory.

Thus, a change to one date will affect the other.

Constructors as type conversion operators

Constructors take a single argument of a given type by value or by const reference

They implicitly convert it into the passed type (see example on next 2 slides)

Constructors as type conversion operators

class my_string {

public:

my_string(unsigned slen) :

rep = new char[slen+1],

len(slen)

{ memset(rep, ‘ ‘, len); };

private:

char* rep;

unsigned len;

Constructors as type conversion operators

my_string s = ‘a’;

char ‘a’ is promoted to unsigned 97a string of 97 spaces is createdprobably not the desired resultKeyword explicit does not allow

implicit conversionsexplicit my_string(unsigned slen);

Destructors

Called automatically when local objects go out of scope

Called implicitly when dynamic objects are deleted

Assignment operator

Similar to the copy constructor, butRe-initializes already constructed objects

Date today; // copy constructor

...

today = “9/20/1999”;

Need assignment operator accepting char*

Assignment operator

Class Date {

Date& operator=(const char* dCptr);

...

}

Date::operator=(const char* dCptr) {

// parse dateCptr into m, d, y

assign(m, d, y);

}

Assignment operator

New C++ feature: overloading operators

Operator overloading - next lectureCompiler generates a default

assignment operator if you do not define one bitwise copy only

Assignment operator

Bitwise copy ok for classes like Date members of simple types only no pointers => no remote ownership

What happens if we bitwise copy an object owning a resource? Same problem as with default copy

constructors

Rule of Big Three

If a class has any of copy constructor destructor assignment operator

It needs all threeDestructor usually shows up firstException: when destructor only

decrements number of instances