56
Constructors and Destructors

Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Embed Size (px)

Citation preview

Page 1: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Constructors and Destructors

Page 2: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 3: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 4: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Initializing simple variables

int counter = 0;

char* owner = NULL;

char name[] = “C++”;

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

Page 5: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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.

Page 6: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 7: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 8: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Date class in C++class Date {

public: // services

Date();

unsigned getMonth();

void incrDay();

unsigned getDOW();

// more services...

private: // state

unsigned year, day, month;

}

Page 9: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 10: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 11: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 12: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Local object

{

Date today; // constructor

// implicitly called

} // destructor implicitly // called here

Page 13: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Dynamic object

{

pstr = new string(“5113”);

...

delete pstr; // destructor called

...

}

Page 14: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Default constructor

Takes no arguments, orAll arguments have default values

Date::Date() {…}

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

Page 15: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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;

}

Page 16: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Default constructor (cont.)

Called when object declared without any arguments

Date d;

string s;

Page 17: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 18: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Disabling a default constructor

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

class BankAccount { ... };

BankAccount ba; // nameless account?

Page 19: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

BankAccount {

...

private:

BankAccount();

}

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

Page 20: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 21: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

}

Page 22: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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.

Page 23: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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)

Page 24: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 25: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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)

Page 26: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Date::assign method

Date::Date () {

// initialize struct tm* tmptr...

// assign checks its arguments

assign(tmptr->tm_month,

tmptr->tm_mday,

1900 + tmptr->tm_year);

}

Page 27: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Date::assign method

Date::Date (constr string DateStr) {

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

// assign checks its arguments

assign(m, d, y);

}

Page 28: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

setMonth(_month);

setDay(_day);

setYear(_year);

// counter of Dates instantiated

numCreated++;

}

Page 29: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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.

Page 30: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Assignment vs. initialization in constructors

Assignment in the constructor body

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

month = m;

day = d;

year = y;

}

Page 31: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 32: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Assignment vs. initialization in constructors

class Student {

private:

string name;

public:

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

...

Page 33: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 34: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

A better way of initialization

Uses initializationAvoids allocation, deallocation,

reallocation for name

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

Page 35: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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)

Page 36: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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...

Page 37: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 38: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 39: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Copy constructor

Initializes a new object from another, existing one

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

Page 40: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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;

}

Page 41: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 42: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 43: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 44: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 45: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Compiler-supplied copy constructor

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

objectSlack bytes problem

Page 46: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 47: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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.

Page 48: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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)

Page 49: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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;

Page 50: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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);

Page 51: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Destructors

Called automatically when local objects go out of scope

Called implicitly when dynamic objects are deleted

Page 52: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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*

Page 53: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

Assignment operator

Class Date {

Date& operator=(const char* dCptr);

...

}

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

// parse dateCptr into m, d, y

assign(m, d, y);

}

Page 54: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 55: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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

Page 56: Constructors and Destructors. Outline zConstructors and Destructors yDefault and compiler-generated yOverloading yMember initialization vs. assignment

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