C Language

OOP, Not Oooops!

It might seem that the problems we've just examined arose because we tried to apply OOP techniques to a non-OOP system interface. Would we avoid problems by starting from scratch? Well, consider a textbook example of OOP-defining a "string" object type. Figure 8.3 shows part of a String class definition. A String object contains the string data in memory allocated by new, and the current string length in an integer member. The code shows one of the constructors, which allocates memory and copies a normal C null-terminated string to the memory pointed to by the object's strdata member. The example also shows an assignment operation, which overloads the = operator. Both the constructor and assignment member functions use the MakeString utility function to allocate memory and copy string data.

One of the intended advantages of this type of string class is to allow code such as the following:

 String a("abc");
 String b("");
 ...
 b=a;

This code is more straightforward than using C's standard string functions, and the String class takes care of managing the necessary memory to hold a string's data, regardless of its size. This "automated" memory management is done in the operator= function by releasing memory assigned to the target of the assignment (e.g., b, above), then allocating enough memory to hold the result of the string expression on the right-hand side of the assignment (e.g., a, above).

But what happens in the following code, where b is defined as a reference to a?

 String a("abc");
 String & b = a; // a and b refer to
          // the same string
 b=a;

Because both a and b refer to the same object, the release of b's memory actually releases a's memory as well-before the copy takes place-and the assignment fails. Note that a similar problem could occur in a plain C (or other language) function that didn't guard against modifying an output argument that might also be an input argument. But common goals of creating C++ classes are to simplify assignment and expressions for new object types and to "hide" memory management. Thus, you'll encounter more occasions where you have to watch out for unexpected ways that member functions, including overloaded operators, can get you in trouble.

In this simplified example, the solution is to avoid releasing the target string's memory, if it points to the same location as the source string. The revised member function is shown in Figure 8.4. To avoid problems like this, remember to implement assignment functions so that the same object can appear on both sides of the = operator. This rule can be quite challenging for classes that overload other operators in addition to =. Which leads to another way to minimize trouble: avoid overloading operators other than =.

by BrainBellupdated
Advertisement: