C++ for Science and Engineering Lecture 32
Total Page:16
File Type:pdf, Size:1020Kb
C++ For Science and Engineering Lecture 32 John Chrispell Tulane University Monday November 15, 2010 Dynamic Memory and Classes We need to address using the new operator inside a class constructor. This brings up some questions: How do we write the class constructor? How do we update the class destructor to deal with the use of new? How will dynamic memory effect how we use and create a C++ class? John Chrispell, Monday November 15, 2010 slide 3/25 Dynamic Memory and Classes Lets remember what new does for us. It allows us to delay making memory decisions untill we come across an instance where we need to assign some memory. This is nice as we don’t have to preallocate all the programs memory. It is also nice as we are not allocating more memory than we need. If you remember from previous notes. We dynamically assign memory in C++ using new. This put the deallocation of freeing of this memory in our hands and we needed to have a corresponding call to the delete operator. This means that class destroctors become needed and not just ornamental. John Chrispell, Monday November 15, 2010 slide 5/25 The StringBad Class To gain insight into how new and delete work for classes we will use the StringBad and later the String class. Note these classes are academic versions of the standard string class. // s t r n g b a d . h −− f l a w e d s t r i n g c l a s s d e f i n i t i o n #include <iostream > #i f n d e f STRNGBAD H #define STRNGBAD H c l a s s StringBad { p r i v a t e : char ∗ s t r ; // p o i n t e r to s t r i n g i n t l e n ; // l e n g t h o f s t r i n g s t a t i c i n t n u m s t r i n g s ; // number o f o b j e c t s p u b l i c : StringBad ( const char ∗ s ) ; // constructor StringBad (); // d e f a u l t constructor ˜StringBad (); // d e s t r u c t o r // f r i e n d f u n c t i o n f r i e n d std::ostream & operator <<(std::ostream & os, const StringBad & st); } ; #en dif John Chrispell, Monday November 15, 2010 slide 7/25 The StringBad Class We should note two things about this class declaration. It uses a pointer-to-char instead of a char array to represent a name. This means it dosn’t allcoate the space itself it uses new in the constructor to do so. The class definition declares the num_strings member to belong to the static storage class. Static class members have the special property that only one copy of the class variable is create. This is independent of the number of objects created. Example: I can have ten StringBad objects. They all share the same num_strings variable. Here we are using the variable to keep track of the number of StringBad objects created. John Chrispell, Monday November 15, 2010 slide 9/25 The StringBad Class Now lets consider the implementation! // s t r n g b a d . cpp −− StringBad c l a s s methods #include <c s t r i n g > // s t r i n g . h f o r some #include ” s t r n g b a d . h” using s t d : : cout ; // initializing s t a t i c c l a s s member i n t StringBad :: num s t r i n g s = 0 ; // c l a s s methods // c o n s t r u c t StringBad from C s t r i n g StringBad :: StringBad( const char ∗ s ){ len = std::strlen(s); // s e t s i z e s t r = new char [ l e n + 1 ] ; // a l l o t s t o r a g e std::strcpy(str , s); // i n i t i a l i z e p o i n t e r n u m s t r i n g s ++; // s e t o b j e c t count cout << n u m s t r i n g s << ” : \”” << s t r << ”\” o b j e c t c r e a t e d \n” ; // For Your Information } StringBad :: StringBad() { // d e f a u l t constructor l e n = 4 ; s t r = new char [ 4 ] ; std::strcpy(str , ”C++” ); // d e f a u l t s t r i n g n u m s t r i n g s ++; cout << n u m s t r i n g s << ” : \”” << s t r << ”\” d e f a u l t o b j e c t c r e a t e d \n” ; // FYI } StringBad ::˜ StringBad() { // n e c e s s a r y d e s t r u c t o r cout << ”\”” << s t r << ”\” o b j e c t d e l e t e d , ” ; // FYI −−n u m s t r i n g s ; // r e q u i r e d cout << n u m s t r i n g s << ” l e f t \n” ; // FYI delete [ ] s t r ; // r e q u i r e d } std::ostream & operator <<(std::ostream & os, const StringBad & st){ os << s t . s t r ; return os ; } John Chrispell, Monday November 15, 2010 slide 11/25 The StringBad Class First we set the default: // initializing s t a t i c c l a s s member i n t StringBad :: num s t r i n g s = 0 ; This is because the declaration of the class is a description (in the .h file) and dosn’t actually allocate the memory, it only describes how it is to be allocated. Static class members are also not stored with the objects and should be initialized separately. We do this with the class method definitions and not in the header, as header files tend to get multiple inclusions, and we don’t want to include the initialization more than once. John Chrispell, Monday November 15, 2010 slide 13/25 The StringBad Class Each constructor has: n u m s t r i n g s ++; Each destructor has: nu m s t ri n gs −−; The constructor: // c o n s t r u c t StringBad from C s t r i n g StringBad :: StringBad( const char ∗ s ){ len = std::strlen(s); // s e t s i z e s t r = new char [ l e n + 1 ] ; // a l l o t s t o r a g e std::strcpy(str , s); // i n i t i a l i z e p o i n t e r n u m s t r i n g s ++; // s e t o b j e c t count cout << n u m s t r i n g s << ” : \”” << s t r << ”\” o b j e c t c r e a t e d \n” ; // For Your Information } uses strlen to determin how much spaces is needed and allocates the space using new. The default constructor works similarly only uses ”C++” as the string. John Chrispell, Monday November 15, 2010 slide 15/25 The StringBad Class The destructor is where the important stuff lives: StringBad ::˜ StringBad() { // n e c e s s a r y d e s t r u c t o r cout << ”\”” << s t r << ”\” o b j e c t d e l e t e d , ” ; // FYI −−n u m s t r i n g s ; // r e q u i r e d cout << n u m s t r i n g s << ” l e f t \n” ; // FYI delete [ ] s t r ; // r e q u i r e d } We used new to create this string we need to use delete to free it! John Chrispell, Monday November 15, 2010 slide 17/25 Sample Program #include <iostream > using s t d : : cout ; #include ” s t r n g b a d . h” void callme1(StringBad &); // pass by r e f e r e n c e void callme2(StringBad); // pass by v a l u e i n t main ( ) { using s t d : : e n d l ; StringBad headline1( ” C e l e r y S t a l k s at Midnight ” ); StringBad headline2( ” L e t t u c e Prey ” ); StringBad sports( ” Spinach Leaves Bowl f o r D o l l a r s ” ); cout << ” h e a d l i n e 1 : ” << h e a d l i n e 1 << e n d l ; cout << ” h e a d l i n e 2 : ” << h e a d l i n e 2 << e n d l ; cout << ” s p o r t s : ” << s p o r t s << e n d l ; callme1(headline1 ); cout << ” h e a d l i n e 1 : ” << h e a d l i n e 1 << e n d l ; callme2(headline2 ); cout << ” h e a d l i n e 2 : ” << h e a d l i n e 2 << e n d l ; cout << ” I n i t i a l i z e one o b j e c t to an o t he r : \ n” ; StringBad sailor = sports; cout << ” s a i l o r : ” << s a i l o r << e n d l ; cout << ” A s s i g n one o b j e c t to an o t he r : \ n” ; StringBad knot; knot = headline1; cout << ” knot : ” << knot << e n d l ; cout << ”End o f main () \ n” ; return 0 ; } void callme1(StringBad & rsb){ cout << ” S t r i n g passed by r e f e r e n c e : \ n” ; cout << ” \”” << r s b << ”\”\n” ; } void callme2(StringBad sb){ cout << ” S t r i n g passed by v a l u e : \ n” ; cout << ” \”” << sb << ”\”\n” ; } John Chrispell, Monday November 15, 2010 slide 19/25 Sample Program The Program has some issues as written.