3.4 Passing Objects by Reference and By Pointer




Previous examples passed objects "by copy" (also know as "by value"). Parameter passing "by copy" has this name because a copy of the object is made and the copy is passed to the called operation. Passing an object by copy is appropriate when the caller wants to be sure that the action taken by the called function or method do not change the objects that the caller passes as parameters.

Call by copy is not appropriate in three situations. First, if the passed object is to be shared between the caller and the called object, passing the object by copy results in the caller and the called code operating on different objects, not a shared object. An example of sharing will be seen below. Second, if the caller wants the called code to modify the passed object then the object itself, and not a copy of it, must be passed. Third, very large objects (e.g., a 1 megabyte bit-mapped image object) are not passed by copy to avoid the overhead in memory usage and copying time. However, these cases must be carefully handled to guard against unintended modifications made by the called code. In general, it is safer to use call by copy unless one of the three cases listed above applies.

A new user interface component will be introduced and used to show the limitation of passing objects by copy and to show how the actual object, and not a copy, can be passed.

A TextBox is a graphical user interface elements that display a changeable line of text in a window. The line of text is displayed in a bordered area that has an optional label on the left side of the bordered area. The definition of the TextBox class is as follows:


 class TextBox {
   private:
 		// private implementation goes here
   public:
     TextBox(Location p, Shape s, char* label);
     TextBox(Location p, Shape s);
     TextBox(char* label);
     TextBox();
    ~TextBox();
     char* GetText();
     void  SetText(char* val);
 };

A TextBox can be created on one of four ways: by specifying the exact location and shape of the box as well as a character string label that is position on the screen adjacent to the box; by specifying the exact location and shape of the box but having no label; by specifying the label and allowing a default location and size to be used; or, finally, by allowing all default values to apply. The current value of the TextBox is changed and queried by the SetText and GetText methods, respectively.

A TextBox must be associated with a Frame object in order to be made visible on the screen. The Frame class is modified, incorrectly at first, to include a method that is intended to display the contents of a TextBox. The incorrect way to extend the Frame class is as follows:

   class BadFrame {				// incorrect version
   private:
		// encapsulated implementation goes here
   public:
   Frame(Location p, Shape s);
  ~Frame();
            
   void     MoveTo( Location newPosition);      // change position
   void     Resize( Shape s);                   // change shape
   Shape    WhatShape();                	// reply current shape
   Location WhereAt();   	        	// reply current location
   void     Display(TextBox box);               // present text in window
           ~BadFrame();
};

In this incorrect version a Display method has been added that takes as its argument a TextBox object that is passed by copy. To see that this is incorrect consider the following program that tries to present a TextBox that changes its value during the program:

  BadFrame window( Location(50, 50), Shape(200, 200));
  TextBox  status( Location(20, 20), Shape(100, 50), "Status:" );
  

  status.SetText("Enter Command");			// prompt message
  window.Display(status);				// prompt displayed

  // user enters command 
  
 
  status.SetText("Executing Command");

  // perform command

  status.SetText("Command Done");

The program expects that the text visible on the screen will change when the user enters a command and when the command is completed. However, the window object was given a copy of the status object - a copy that never changes. The program is modifying the original status while the window is displaying the unchanging contents of the copy. What is needed is a means for the program and the window object to share a copy of the same object.

Objects can be passed "by reference" and "by pointer", in either case the object is not copied. The syntax for passing parameters by reference and by pointer is shown in the next version of the Frame class.

  class Frame {				// Version 5
   private:
		// encapsulated implementation goes here
   public:
   Frame(Location p, Shape s);
  ~Frame();
            
   void     MoveTo( Location newPosition);      // change position
   void     Resize( Shape s);                   // change shape
   Shape    WhatShape();                	// reply current shape
   Location WhereAt();   	        	// reply current location
   void     Display(TextBox& box);              // by reference
   void     Display(TextBox* box);              // by pointer
           ~Frame()
  };

The specification "TextBox&" denotes passing a TextBox object by reference. The specification "TextBox*" denotes passing a TextBox object by pointer.

Using the two Display methods is shown in the code below. In this example the object box1 is passed by reference. From the caller's point of view, there is no difference in the syntax of passing an object by copy or by reference. There is, however, a major difference in effect (i.e., the semantics of the operation). The object box2 is a dynamic object that is passed by pointer. Notice that the "->" operator must be used to invoke the SetText method on box2 since it is a dynamic object. Finally, box3 shows that non-dynamic objects can also be passed by pointer by using the "address of" operator (the "&" preceeding a variable name) to obtain a pointer to the object.


// Declarations

   Frame   window(Location(50, 50), Shape(100, 100));

   TextBox box1("First:") , box3("Second:");
   TextBox* box2;
   TextBox* box4;

// code

   box2 = new TextBox("Third:");
   box4 = new TextBox("Fourth:");

   box1.SetText("apple");
   box2->SetText("orange");
   box3.SetText("banana");
   box4->SetText("cherry");

   window.Display(box1);		// uses by reference
   window.Display(box2);		// uses by pointer
   window.Display(&box3);		// uses by pointer
   window.Display(*box4);		// uses by reference



Next Stop


Exercises

  1. Write a program using a TextBox that shows your name in a window. Choose an appropriate label for the TextBox.

  2. Write a program that displays two integer values, each in a separate labelled TextBox. Use the function "char* itoa(int)" to convert an integer to a character string. To use itoa(), include the header file "Base.h".

  3. Use the BadFrame and Frame classes to write a program that illustrates the difference between passing by copy and passing by reference as follows. Create two windows on the screen, one a BadFrame and one a Frame. Create two TextBoxes. One TextBox has the initial value of "Passed by Copy" and is displayed in the window created from the BadFrame class. The other TextBox has the initial value of "Passed by Reference" and is displayed in window created from the Frame class. Then set the text in both TextBoxes to the string "SUCCESS!!!".

  4. Revise the Shrinking Window program so that the window contains two TextBoxesthat display the current height and width of the window. The window should also contain a Message with your full name.

  5. Revise the Border Walk program so that the window contains two TextBoxes that display the current location of the window. The window should also contain a Message with your full name.

Last Updated: May 24, 1996 / kafura@cs.vt.edu