Top Banner
Copy Control Joe Meehean
58

Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Dec 26, 2015

Download

Documents

Isaac Parker
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control

Joe Meehean

Page 2: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

More Class Responsibilities• When making a new type (i.e., class) we must specify what

happens when it is:• Copied• Assigned• Destroyed

2

Page 3: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• Used to create a new copy of a class object• Takes a single parameter of same class type (usually const)• Has no return type• Declaration syntax• Class(const Class& orig)• e.g., IntMatrix(const IntMatrix& orig);

3

Page 4: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• Usage syntax• Class varname(origname)• e.g.,

IntMatrix a(4,4);IntMatrix b(a);

• Definition requirements• must initialize all data members• data members should match values of original’s data members

4

Page 5: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor

5

// (header) .hclass HitSong{ Song hit_song_; int chart_rank_; int singles_sold_;

HitSong( Song& song, int chart_rank, int singles_sold);

HitSong( const HitSong& orig);};

Page 6: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor

6

HitSong::HitSong(const HitSong& orig) :hit_song_(orig.hit_song_),chart_rank_(orig.chart_rank_),singles_sold_(orig.singles_sold_)

{ // nothing to do here}

• Note: this constructor can access private data of orig• Because both this and orig are instances of HitSong

Page 7: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• What if we don’t write a copy constructor?• Compiler creates one for us• called the synthesized copy constructor• created even if we define other constructors

• Synthesized copy constructor• performs memberwise initialization of member data• initializes each member variable by copying original

member variable• if member variable is a built-in (primitive), just copies the bits• if member variable is a class, uses the class’s copy constructor• if member variable is an array, copies each element 7

Page 8: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• How do we prevent copies of our class?• Approach 1: make copy constructor private• prevents non-class code from making copies• friends and member functions of class can still make copies

• Approach 2: make undefined, private copy constructor• declare it

• e.g., IntMatrix(const IntMatrix& orig);• do not define it• perfectly legal• non-class code gets compiler errors• class code and friends get linking errors 8

Page 9: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• When is it used• Explicitly in code• e.g., IntMatrix b(a);

• Passing class instance as an argument to a function• non-reference• e.g., flip(IntMatrix a);

• Returning a non-reference instance from a function• e.g., return a;

9

Page 10: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• When is it used• Explicitly initializing an array

10

Song songs[] = { Song(“Simply Irresistable”, “Robert Palmer”), Song(“The Power of Love”, “Huey Lewis & The News”), Song(“In the Air Tonight”, “Phil Collins”)};

• Uses constructor to create temporary Songs • Initializes array using copies of temporary Songs

Page 11: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Constructor• Classes best practices: always define a • default constructor• copy constructor

11

Page 12: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Questions?

12

Page 13: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• If you implement a class,

you need to control what happens during an assignment• e.g., b = a;• make sure data is copied correctly from a to b

• How do we write a function for an operator?

13

Page 14: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• How do we write a function for an operator?• syntax:

return_type operator symbol(type operand1, type operand 2, …)• e.g.,

int operator + ( const int& a, const int& b);• The assignment operator (=) often returns a reference to the

assigned variable• allows: a = b = c;• e.g.,

int& operator = (int& a, int& b);• More on this in future lectures

14

Page 15: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• When we write an operator function for a class,

the first parameter is implicitly the this parameter

• Assignment operator for a class declaration syntax• Class& operator =(const Class& rhs)• e.g., HitSong& operator =(const HitSong& rhs)

• Assignment operator for a class definition syntax• Class& Class::operator =(const Class& rhs){ … }• e.g., HitSong& HitSong::operator =(const HitSong& rhs)

15

Page 16: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• When doing assignment we are copying values from one

instance of a class to another• unlike copy constructor, both instances are already initialized

16

Song aSong(“Twilight Zone”, “Golden Earring”);Song bSong(“Radar Love”, “Golden Earring”);

aSong = bSong;

Page 17: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator

17

HitSong& HitSong::operator =(const HitSong& rhs){ if( this != &rhs ){

this->song_ = rhs.song_; this->chart_rank_ = rhs.chart_rank_; this->singles_sold_ = rhs.singles_sold_;

}

return *this;}

Page 18: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator

18

HitSong& HitSong::operator =(const HitSong& rhs){ if( this != &rhs ){

this->song_ = rhs.song_; this->chart_rank_ = rhs.chart_rank_; this->singles_sold_ = rhs.singles_sold_;

}

return *this;}

Page 19: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator

19

HitSong& HitSong::operator =(const HitSong& rhs){ if( this != &rhs ){

this->song_ = rhs.song_; this->chart_rank_ = rhs.chart_rank_; this->singles_sold_ = rhs.singles_sold_;

}

return *this;}

Page 20: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• What if we don’t write an assignment operator?

• Compiler makes a synthesized assignment operator• Performs memberwise assignment• each member variable is assigned member variable from rhs• built-ins use a bitwise assignment• classes uses their own assignment operator• arrays are assigned element by element

• Returns *this

20

Page 21: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• What happens in this code?

21

Song aSong(“Hotel California”, “Eagles”);Song b = aSong;

Page 22: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• What happens in this code?

22

Song aSong(“Hotel California”, “Eagles”);Song b = aSong;

• b is created using Song’s copy constructor

Page 23: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Assignment Operator• Classes best practices: always define a • default constructor• copy constructor• assignment operator

23

Page 24: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Questions?

24

Page 25: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• How do we clean up the memory we allocated with

the constructor?

• Each class needs a destructor method• one more responsibility of class creator• specifies how to clean up memory allocated for member data• complement of constructors

25

Page 26: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• When is the destructor called?

• Automatic objects• automatically destroyed when they go out of scope

26

int HitSong::func(){ Song aSong(“Could well be in”, “The Streets”); // other stuff ...}

aSong is destroyed using its destructor

Page 27: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• When is the destructor called?

• Dynamically allocated objects• destroyed explicitly using delete

27

int HitSong::func(){ Song * pSong = new Song( “Could well be in”,

“The Streets”); // other stuff ... delete pSong;}

Memory pointed to by pSong is destroyed using its destructor

Page 28: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• When is the destructor called?

• Dynamically allocated objects• if never deleted, it is never destroyed

28

int HitSong::func(){ Song * pSong = new Song( “Could well be in”,

“The Streets”); // other stuff ...}

pSong lives on forever. We cannot get access to it either.

Page 29: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• When is the destructor called?

• Arrays of objects • deleted when array is destroyed

29

int HitSong::func(){ Song songs[10]; // other stuff ...}

each Song in songs is destroyed using its destructor

Page 30: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• Declaration syntax• virtual ~Class();• e.g., virtual ~Song();• takes no parameters• has not return type• ignore what virtual means for now, just include it

• Definition syntax• Class::~Class(){• e.g., Song::~Song(){

30

Page 31: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• Usage syntax• how do we call the destructor• you don’t, its called automatically in cases described earlier

31

Page 32: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• What happens if we don’t define one?• Compiler defines a destructor for you.• destroys each non-static member variable• using same rules like the object went out of scope• destroys them in reverse order of declaration

• What happens if we do define one• compiler defines one even if you define one too• compiler runs its destructor after yours

32

Page 33: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• Why bother to define a destructor if the compiler already does

it for you?• May need to deallocate non-automatic resources• dynamically allocated memory• close open files• amongst others (more on this in OS)

• What should our destructor do?• if you don’t dynamically allocate memory (or other resources)• nothing

33

Page 34: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Destructor• Classes best practices: always define a • default constructor• copy constructor• assignment operator• destructor

• Actually…• you should decide for yourself, except• Big Three: copy constructor, assignment operator, and destructor• if you define a one of Big Three, should always define other two

34

Page 35: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Questions?

35

Page 36: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Pointers make copy control (Big Three) more difficult• Class designer must make one of two choices:• Shallow copy• copy and assignment should copy only the pointer

• Deep copy• copy and assignment allocate new memory and copy object

pointer points to

36

Page 37: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Assume

37

Song::Song( const char* name, const char *artist){ name_ = new char[512]; // SHOULD USE STRLEN artist_ = new char[512]; strcpy(name_, name); strcpy(artist_, artist);}

void Song::setArtist(const char* artist){ strcpy(artist_, artist); // SHOULD CHECK LENGTH}

void Song::deleteName(){ delete name_; name_ = NULL;}

Page 38: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Shallow copying

38

Song::Song(const Song& orig){ name_ = orig.name_; artist_ = orig.artist_;}

Page 39: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Shallow copying

39

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);}

Bob Dylan

All along…

aSong :

name_

artist_

Page 40: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Shallow copying

40

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);

Song bSong(aSong);}

Bob Dylan

All along…

bSong :

name_

artist_

aSong :

name_

artist_

Page 41: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Shallow copying

41

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);

Song bSong(aSong);

aSong.setArtist(“Jimi Hendrix”);}

Jimi Hendrix

All along…

bSong :

name_

artist_

aSong :

name_

artist_

Page 42: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Shallow copying

42

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);

Song bSong(aSong);

aSong.setArtist(“Jimi Hendrix”); aSong.deleteName();}

Jimi Hendrix

All along…

bSong :

name_

artist_

aSong :

name_

artist_

Director’s Cut

Page 43: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Dangers of shallow copies• data modified out from under you• data destroyed, left pointing at garbage• program crashes or acts strangely

43

Page 44: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

44

Song::Song(const Song& orig){ name_ = new char[strlen(orig.name_)+1]; artist_ = new char[strlen(orig.artist_)+1]; strcpy(name_, orig.name_); strcpy(artist_, orig.artist_);}

Page 45: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

45

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);}

Bob Dylan

All along…

aSong :

name_

artist_

Page 46: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

46

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);

Song bSong(aSong);}

Bob Dylan

All along…

bSong :

name_

artist_

aSong :

name_

artist_Bob Dylan

All along…

Page 47: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

47

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);

Song bSong(aSong);

aSong.setArtist(“Jimi Hendrix”);}

Jimi Hendrix

All along…

bSong :

name_

artist_

aSong :

name_

artist_Bob Dylan

All along…

Page 48: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

48

void main(){ Song aSong(“All along the watchtower”,

“Bob Dylan”);

Song bSong(aSong);

aSong.setArtist(“Jimi Hendrix”); aSong.deleteName();}

Jimi Hendrix

All along…

bSong :

name_

artist_

aSong :

name_

artist_Bob Dylan

All along…

Director’s Cut

Page 49: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• If you don’t define a copy constructor or an

assignment operator• synthesized versions perform a shallow copy

• If you define a deep copy constructor and assignment operator, but not a destructor• you will leak memory

49

Page 50: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

50

Song::operator =(const Song& orig){ if( this != &orig ){ delete name_; delete artist_;

name_ = new char[strlen(orig.name_)+1]; artist_ = new char[strlen(orig.artist_)+1]; strcpy(name_, orig.name_); strcpy(artist_, orig.artist_); } return *this;}

Page 51: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

51

Song::operator =(const Song& orig){ if( this != &orig ){ delete name_; delete artist_;

name_ = new char[strlen(orig.name_)+1]; artist_ = new char[strlen(orig.artist_)+1]; strcpy(name_, orig.name_); strcpy(artist_, orig.artist_); } return *this;}

Page 52: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

52

Song::operator =(const Song& orig){ if( this != &orig ){ delete name_; delete artist_;

name_ = new char[strlen(orig.name_)+1]; artist_ = new char[strlen(orig.artist_)+1]; strcpy(name_, orig.name_); strcpy(artist_, orig.artist_); } return *this;}

Page 53: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

53

Song::~Song(){ delete name_; delete artist_;}

Page 54: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• When a shallow copy is really a deep copy• if the member object is not really owned by this class• if we just have a reference to another objects data, we should not

copy it or destroy it

• How can I tell if my class owns an object?• if you created it or are going to destroy it, it is yours• if you new’ed it, you should delete it• if you are going to delete it, you should new it

54

Page 55: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• When a shallow copy is really a deep copy• which class owns which

55

class Song{ char *name_; char *artist_; Album *album_;};

class Album{ Song *songs_; int number_of_songs;};

Page 56: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying that looks shallow

56

Song::operator =(const Song& orig){ if( this != &orig ){ delete name_; delete artist_;

name_ = new char[strlen(orig.name_)+1]; artist_ = new char[strlen(orig.artist_)+1]; strcpy(name_, orig.name_); strcpy(artist_, orig.artist_);

album_ = orig.album_; } return *this;}

Page 57: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Copy Control and Pointers• Deep copying

57

Album::operator =(const Album& orig){ if( this != &orig ){ delete songs_; number_of_songs_ = orig.number_of_songs; songs_ = new Song[number_of_songs]; for(int i = 0; i < number_of_songs; i++){ songs_[i] = origs.songs_[i]; songs_[i].album = this; } } return *this;}

Page 58: Copy Control Joe Meehean. More Class Responsibilities When making a new type (i.e., class) we must specify what happens when it is: Copied Assigned Destroyed.

Questions?

58