Presentation is loading. Please wait.

Presentation is loading. Please wait.

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.

Similar presentations


Presentation on theme: "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."— Presentation transcript:

1 Copy Control Joe Meehean

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

3 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

4 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

5 Copy Constructor 5 // (header).h class HitSong{ Song hit_song_; int chart_rank_; int singles_sold_; HitSong( Song& song, int chart_rank, int singles_sold); HitSong( const HitSong& orig); };

6 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

7 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

8 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

9 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

10 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

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

12 Questions? 12

13 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

14 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

15 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

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

17 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; }

18 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; }

19 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; }

20 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

21 Assignment Operator What happens in this code? 21 Song aSong(“Hotel California”, “Eagles”); Song b = aSong;

22 Assignment Operator What happens in this code? 22 Song aSong(“Hotel California”, “Eagles”); Song b = aSong; b is created using Song’s copy constructor

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

24 Questions? 24

25 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

26 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

27 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

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

29 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

30 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

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

32 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

33 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

34 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

35 Questions? 35

36 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

37 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; }

38 Copy Control and Pointers Shallow copying 38 Song::Song(const Song& orig){ name_ = orig.name_; artist_ = orig.artist_; }

39 Copy Control and Pointers Shallow copying 39 void main(){ Song aSong(“All along the watchtower”, “Bob Dylan”); } Bob Dylan All along… aSong : name_ artist_

40 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_

41 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_

42 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

43 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

44 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_); }

45 Copy Control and Pointers Deep copying 45 void main(){ Song aSong(“All along the watchtower”, “Bob Dylan”); } Bob Dylan All along… aSong : name_ artist_

46 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…

47 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…

48 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

49 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

50 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; }

51 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; }

52 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; }

53 Copy Control and Pointers Deep copying 53 Song::~Song(){ delete name_; delete artist_; }

54 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

55 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; };

56 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; }

57 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; }

58 Questions? 58


Download ppt "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."

Similar presentations


Ads by Google