Selected C Example 19

 <  Free Open Study  >  

Selected C++ Example #19

 // Chapter 9 Example #1  // This C++ example illustrates a minimal public interface // implementation for a reference-counted String class. The // minimal interface used is the one described in Chapter 9 // of this text. The code is actually three different files, // string.hxx (the header file) , string.in1 (the inline // function file included into the header file), and string.cpp // (the C++ methods file). The three files are provided to // illustrate the code organization as well as the details of // the interface. Extra methods/operators are shown in the // class definition but are not provided in the source code // (for brevity). // String.hxx // This file contains the class definition for the class String. #ifndef _STRING_ #define _STRING_ #include <iostream.h> #include <string.h> // The external definition of the global string that contains the // name of this class 's name, i.e. , String. extern char* String_type; class String {   struct StringRep {            char* s;            int ref_cnt;            StringRep(const char*);      };      StringRep *str;      void disconnect_self(); public:      // Constructors and Destructors      String(const char*);      String(const String&);      ~String();            // Required functions for each class      const char* type() const;      String& shallow_copy(const String&);      String& deep_copy(const String&);      String* shallow_copy()const;      String* deep_copy()const;      int equal(const String&) const;      int same(const String&) const;            // Additional member functions      String& upper_case();      String& lower_case();      String& upper_case(const String&);      String& lower_case(const String&);      String& reverse();      intlength()const;       //Required operators      String&operator=(const String&);      int operator==(const String&) const;      int operator!=(const String&) const;      friend ostream& operator<<(ostream&, const String&);      friend istream& operator>>(istream&, String&);            // Additional operators      String& operator=(const char*);      String operator+(const String&)const;      String& operator+=(const String&);      int operator<(const String&) const;      int operator>(const String&) const;      int operator<=(const String&) const;      int operator>=(const String&) const;      String operator~() const;      char& operator[](intindex) const;            // Required self-test function.      static void test(); }; #include ''string.inl'' #endif // String.inl // This file contains all the inline function definitions used by // the class String. // The function that returns the type of the class String is // implemented as an inline function, which returns the global // type string of this class. This global variable contains the // constant String, is defined in String.cxx, and is used to // facilitate fast testing of the type of an object. For example, //      if (o.type() == String_type) { // as opposed to //      if (!strcmp(o.type(), ''String'')) { inline const char* String::type() const {      return(String_type); } // The constructor for String, which takes a character pointer as // an argument, creates a new StringRep structure on the heap // and allocates space within it for the String' s characters. // These characters are copied into the allocated space, and the // reference counter is assigned to one. inline String::String(const char* s) {      str = new StringRep(s); } // The destructor for the String class must disconnect the String // object from its StringRep implementation. The disconnect_self // function is a private function that decrements the reference // counter and, if it goes to zero, cleans up the object. inline String::~String() {      disconnect_self(); } // The shallow copy function for the String class, which takes // zero arguments, is implemented as an inline function call to // the copy constructor for Strings. The object that calls this // constructor is allocated space on the heap. The source of the // copy is the current object, which called the shallow copy // function in the first place. inline String* String::shallow_copy() const {      return(new String(*this)); } // The deep copy function for the String class, which takes zero // arguments, is implemented as an inline function call to the // constructor for Strings that takes a character pointer as an // argument. This heap object encapsulates the character array // in the current object (i.e., *this). inline String* String::deep_copy() const {      return(new String(str->s)); } // The equal function for the String class is implemented as an // inline function call to the standard C library function // ''strcmp,'' which tests the equality of two strings inline int String::equal(const String& rhs) const {      return(!strcmp(str->s, rhs.str->s)); } // The ''same'' function for the String class is implemented as an // inline function that tests the StringRep pointers to ensure // that they are the same. If they are the same, then the two // String objects are the exact same object or shallow copies of // each other. inline int String::same(const String& rhs) const {      return(str == rhs.str); } // The overloaded equivalence operator is implemented as an // inline function call to the equal function defined on the // class String. This function returns one if the two strings are // equivalent (i.e., contain the same characters) and zero // otherwise. For testing exact equality, see the function // ''same()'' above. inline int String::operator==(const String& rhs) const {      return(equal(rhs)); } // The overloaded nonequivalence operator is implemented as // an inline function call to the equal function defined on the // class String. The return value of the equal function is // inverted before being returned. This operator returns one if // the strings are not equal and zero otherwise. inline int String::operator!=(const Strings rhs) const {      return(!equal(rhs)); } // String.cxx // This file contains the member functions for the class String. #include ''string.hxx'' char* String_type= ''String''; // The constructor for StringRep is used as a support function in // several of the member functions for Strings. It takes a // character pointer as an argument, allocates space for it, // copies the characters into this allocated space, and assigns // its reference count to one. String::StringRep::StringRep(const char* old_s) {      if (old_s != NULL) {           s = new char[strlen(old_s)+1];           strcpy(s, old_s);      }      else {           s = NULL;      }      ref_cnt = 1;  } // The disconnect_self function is a private function that will // separate a String object from its internal StringRep node. // This process involves decrementing the reference counter in // the StringRep node and, if it is zero (indicating that the // String disconnecting itself is the last object pointing to the // StringRep), the String object cleans up the StringRep object. void String::disconnect_self() {      if (--str->ref_cnt == 0) {           delete str->s;           delete str;      } } // The copy constructor for the String class will increment the // ref_cnt field of the String on the right-hand side of the  //initialization, i.e., the argument rhs. The StringRep pointer // of the new object is then initialized to point at the existing // StringRep (to which rhs is also pointing). String::String(const String& rhs) {      rhs.str->ref_cnt++;      str = rhs.str; } // The shallow copy function for Strings will simply assign the // pointer to the StringRep object to point at the StringRep of // the object on the right-hand side. The String object on the // left-hand side of the function call (i.e., this) must first // disconnect itself from its StringRep. String& String::shallow_copy(const String& rhs) {      disconnect_self();      str = rhs.str;      str->ref_cnt++;      return(*this); } // The deep copy function for the String class (which takes an // additional argument) first disconnects the node from its // current StringRep and then creates a new StringRep, // assigning that StringRep to the value of the character array // stored in the StringRep of the rhs String object. This // function returns a reference to the String object on the left- // hand side (i.e., *this) to facilitate nested function calls. String& String::deep_copy(const String& rhs) {      if (!same(rhs)){           disconnect_self();           str = new StringRep(rhs.str->s);      }      return(*this); } // The overloaded operator= function for the String class must // first disconnect the String object on the left-hand side from // its associated StringRep. It then assigns the StringRep pointer // in that object to point at the StringRep object in the String // object on the right-hand side of the assignment operator. // This function returns a reference to the String object on the // right-hand side in order to facilitate nested function calls. String& String::operator=(const String& rhs) {      if (!same(rhs)) {           disconnect_self();           str = rhs.str;           str->ref_cnt++;      }      return(*this); } // The overloaded assignment operator for the String class, which // takes a character pointer as an argument, first disconnects // the string from its StringRep data member. It then creates a // new StringRep structure and encapsulates the argument array // of characters (i.e., rhs) into it. String& String::operator=(const char* rhs) {      disconnect_self();      str = new StringRep(rhs);      return(*this); } // The overloaded input and output operators for Strings simply // read in the character array using standard C++ functions. // The overloaded input operator will first disconnect the existing // String from its associated StringRep object. ostream& operator<<(ostream& o, const String& rhs) {      o << rhs.str->s;      return(o); } istream& operator>>(istream&i, String& rhs) {      char buf[512];      rhs.disconnect_self();      i >> buf;      rhs.str = new String::StringRep(buf);      return(i);  } 
 <  Free Open Study  >  


Object-Oriented Design Heuristics
Object-Oriented Design Heuristics (paperback)
ISBN: 0321774965
EAN: 2147483647
Year: 1996
Pages: 180

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net