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
|
Exercises |