C++ Class Part 4

By Terry Norton

Welcome to lesson 4 about C++ Functions.

Objectives for Chapter 7
By the end of Chapter 7 you should understand the following concepts:
 * Defining, prototyping, and calling functions
 * The interrelationships of type, parameter list, and address of a function
 * Passing and processing arrays with functions
 * A special case of arrays and functions: text strings
 * Preventing a function from changing data it is sent
 * Recursive functions and how they work
 * Using structures with functions
 * Using pointers to functions

Using functions in C++
We have already used quite a number of functions up to this point that were supplies by the library files included with OpenWatcom. All we had to do is  #include  the file and then call the functions. These parts:
 * Define the function
 * Prototype the function

have already been done for you when you use a library file. When we create our own functions, we have to provide these steps ourselves before we can call the function.

Function Arguments and Passing by Value
When I started to learn programming, I was totally confused with functions. When a function was called, the argument might be a certain variable name, but when I tried to follow the next step in the function itself, the variable name wasn't there. I couldn't make the connection of how this mysterious processed worked. Another case of making a simple process difficult in my mind. Figure 7.2 in the book is a perfect example that blocked my learning.

You see a call to the cube function: double volume = cube(side); I could easily see that the variable side was used as an argument. But then follow this down to the cube function: double cube(double x) What happened to side? I was lost already because side was nowhere to be found in the function. I just didn't get it, not even in Rexx. What I finally learned is that this magic was a simple assignment to another variable name. Technically, x = side was being performed, but nothing I read said this. I don't remember when the lights finally turned on, all I know is this little roadblock stopped me from proceeding for a long time.

Passing by Value means that both variables, side and x</tt>, each have the same value now, 5. When the cube</tt> function finishes, the value returned is assigned to the variable volume</tt>, side</tt> is still 5 and x</tt> vanishes from memory. In other words, the cube</tt> function had no effect on the value of side</tt>. A copy of its value, 5, was passed (assigned) to the cube</tt> function variable x</tt>.

Functions and Arrays
If you recall, right after we learned about pointers and how to dereference a pointer to get the value stored at an address, we went on to learn about arrays. The array name is a pointer, meaning the array name holds the address of the first element of the array.

In Listing 7.4, arrfun1.cpp</tt>, the array cookies</tt> is an argument for the sum_arr</tt> function. Now stay with me here. Functions work with copies of the variables passed to them. Since copies of variables are passed into functions, and C++ specifies that an array name is really a pointer (an address), a copy of the pointer (an address) is being passed into the function.

What this means is that the function is going to be working with the data in the original array. Why? Because all we did was tell the function where the array is located, its address. We didn't pass into the function a copy of the array's data. So basically there are now two pointers pointing to the same address in memory, the array name cookies</tt>, and the array name arr</tt> inside the function. When the function ends, any variables inside the function cease to exist.

On page 258, you see this: cookies == &cookies[0]; Don't let this confuse you, this isn't part of the code. It's just an explanation to show that cookies is the same as the address of the array's first element. Remember, &</tt> is the address-of operator.

The main point to remember, when dealing with arrays in function calls, is that another way to declare a pointer is arr[]</tt>, see figure 7.4.

Functions Using Array Ranges
Listing 7.8, <tt>arrfun4.cpp</tt>, may look odd. The function <tt>sum_arr</tt> sums the total cookies eaten in the cookies array, but there's not the usual array element syntax using the <tt>[ ]</tt>. The function is simply using pointer arithmetic to access each array element, and then dereferencing the pointer to get the value in the element. <tt>pt</tt> is the pointer to the array. When you add 1 to <tt>pt</tt>, <tt>pt + 1</tt>, you are now pointing to the next element address in the array. This is what the <tt>for</tt> loop is doing, stepping through the array elements by adding 1 to the pointer. Each time <tt>pt</tt> is incremented, the next element in the array is being pointed to, and to get the value at that memory address, the pointer is dereferenced, <tt> *pt </tt>.

Functions and Two-Dimensional Arrays
This section looks rather confusing. I've had to reread it several times. A two-dimensional array is actually an array of arrays. One dimensional arrays are usually an array of <tt>int</tt> or an array of <tt>char</tt>, etc. On page 272, we have the <tt>data</tt> array which has 3 elements. Each of these 3 elements is pointing to an array of 4 <tt>int</tt> values.

Bottom line: the array name is a pointer to the first element of an array, we just learned this. There are 3 arrays containing 4 <tt>int</tt> values, therefore there are 3 memory addresses which point to the first element of each array. These 3 memory addresses are stored in an array called the <tt>data</tt> array.

If you were to look at the actual memory locations, you would simply see a section of memory with 12 addresses in sequence. The first location is pointed to by the array name <tt>data</tt>. This is also the address of the first 4 element array. To point to the next 4 element array, you would add 4 to the pointer, <tt>data = data +4</tt>, or <tt>data += 4</tt>. Adding 4 just means you have skipped over the 4 elements in the first array to be at the beginning of the second array. To point to the third and final array, add 4 again, <tt>data += 4</tt>. At the bottom of page 272 you see a <tt>for</tt> loop. The first loop does just what I described. The nested <tt>for</tt> loop points to each element of the 4 element arrays.

I took the code on page 272 to show how the memory addresses are all in sequence, and also the size of each array element since this determines the bytes between elements. As we have learned, arrays cannot be a parameter in a function, but a pointer can. We also learned that when dealing with functions and arrays, there are two ways to specify an array pointer, <tt>int *ar2</tt>, and <tt>ar2[]</tt>. So in the declaration for the <tt>sum</tt> function: int sum(int ar2[ ][4], int size); <tt>ar2[]</tt> is a pointer, pointing to an array of four <tt>int</tt>.

Functions and C-Style Strings
Here we reinforce what we learned about <tt>char</tt> arrays. See Chapter 4, pages 140 to 145. When you pass a pointer to <tt>cout</tt> that is the address of a string array, <tt>cout</tt> prints the string. That's the way <tt>cout</tt> is told to work. <tt>cout</tt> sees that the pointer is type <tt>char</tt> (arrayname is a pointer), and sends the string to the screen instead of printing the address to the screen. If you do want the address to print, then you have to typecast the pointer to something else. In other words, make <tt>cout</tt> see it as a pointer to something other than a <tt>char</tt> array (see the bottom of page 143).

The main point to remember about passing arrays to functions, you can't, but you can pass a pointer which points to the array. String arrays are even more different, all strings end with the null character, <tt>\0</tt>. So passing a string array (really the pointer) means you don't need to pass the size of the array as a function parameter (argument), as the null character can be used to detect the end of the string.

Functions That Return Strings
A brief note about Listing 7.10, <tt>strgback.cpp</tt>. You'll notice that the <tt>buildstr</tt> function has a <tt> * </tt> symbol before it: char * buildstr(char c, int c); This declaration may appear like it's declaring a function as a pointer, but it's not. Remember that functions have to declare a return type. For instance if the declaration was written this way: int buildstr(char c, int c); you'd easily recognize that the function was returning an integer type. Well, all the <tt>char *</tt> is saying is that the function is returning a pointer-to-char type. It's just returning a pointer, a memory address.

That takes care of arrays. In Object Rexx, I very seldom used an array, The reason is because there are Container Classes that are so much easier to work with. We will get to Containers in C++ eventually.

Functions and Structures
The book explains this section very well, so there's no need to add anything that just might add confusion. I will just point to page 279, first sentence under the subsection Another Example. We are learning material very much related to Classes, so pay very close attention. Even then, when we start passing Class objects we're going to learn an even better way in the next chapter, passing-by-reference.

Passing Structure Addresses
Here we are shown how to use pointers with functions and structures. In the previous section you learned how to pass structures by value in functions. This uses a lot of memory if the structure happens to be large because pass-by-value means copies are used in the functions. Using the same code but modifying it to pass pointers (addresses) in the functions means there's no copies being made, you are working with the original structure and its data.

The main modification to the code is in the <tt>rect_to_polar</tt> function. Previously it returned a structure which was assigned to the <tt>polar</tt> type variable <tt>pplace</tt>. With pointers there's no need to return a structure from the function since we're already working with the original structure, not a copy of it. So the needed modification is to change the <tt>rect_to_polar</tt> function to also pass the address of the polar structure <tt>pplace</tt>.

As you can see in the new code, the <tt>rect_to_polar</tt> function is called but isn't used to assign any return value to <tt>pplace</tt> since it's already available in the function block code.

Recursive Functions
I don't have any real life experience with recursive functions since I never needed to use them. Whether you use them or not, it's good to know what they can do when needed. I would tend to just file away in my mind that they exist. When I ever come to a point where I might need to use recursion, I'll just look it up again.

Pointers to Functions
This is more material that I'm going to file away. I'll probably be overwhelmed enough just using the normal methods of calling functions using pointers. However, it must also be remembered that making a function call means you are infact telling your program to jump to the memory address of the function anyway.

Questions for Chapter 7
True or False
 * 1) Every function, including <tt>main</tt>, must have at least one <tt>return</tt> statement.
 * 2) A function's single <tt>return</tt> statement must be the last statement at the end of the function.
 * 3) An array variable cannot be returned from a function by value.
 * 4) The pointer notations <tt>int *arr</tt> and <tt>arr[]</tt> are identical and either may be substituted for the other in any part of a C++ program.
 * 5) Either passing a variable by value or by using <tt>const</tt> will prevent the called function from modifying the data.
 * 6) One good reason to pass a pointer to a structure rather than the structure itself is because of the processing time it takes to make a copy of the structure.
 * 7) In essence, the extraction operator is implemented as a class function in C++.

Objectives for Chapter 8
By the end of Chapter 8, you should understand these concepts:
 * Inline functions and when they are appropriate
 * Reference variables, the other side of pointers
 * Giving a function the capability to modify data by using reference variables
 * Using default arguments to cover the "normal" situation
 * Function overloading/polymorphism: customizing the function to the data
 * Templates to partially automate function overloading to save work and reduce errors

Reference Variables
This is where things become a little bit easier compared to pointers. We've learned how to work with variables as either a simple name or a pointer to the address of the variable. Now we have a reference to a variable. The big benefit is that a reference eliminates having to use a pointer as a function argument, along with the pointer dereferencing symbol,  * , to be able to work with the data.

Bottom line: passing-by-reference means the function statements are working with the original data, not a copy of it. Yet, we don't need to use a pointer and pointer dereferencing to accomplish this feat. It's just plain easier to look at the code as well.

Technically, the reference symbol, <tt>&</tt>, is behaving just like the address-of operator. In my little modification of Listing 8.5, <tt>cubes.cpp</tt>, I used the address-of operator to check the address of the variable <tt>x</tt> and the variable <tt>a</tt>. They are the same, as they should be. We know that to get the address of x we use &x. So look at the cube declaration: double cube(double &a); When we call the cube function: cout << cube(x); we are in reality sending the address of <tt>x</tt> into the <tt>cube</tt> function. This address is now assigned (copied) to <tt>&a</tt>, which is the address of the new variable <tt>a</tt>. So <tt>&x</tt> and <tt>&a</tt> are both the same address, just as if a pointer had been used. As a result, the variable <tt>a</tt> is an alias for the variable <tt>x</tt> since they both reference the same value that's stored at the one address. So inside the function, when we change the value of <tt>a</tt>, <tt>x</tt> is being changed because they both reference the value stored at the same address.

Using References with a Structure
In Listing 8.6, <tt>strtref.cpp</tt>, find the statement use(use(looper)); The <tt>use</tt> function has a reference parameter, it also returns a reference, so you can substitute looper with <tt>use(looper)</tt>. In other words, when the <tt>use</tt> function is finished doing its thing, it returns a reference-to-looper back to the code that called the <tt>use</tt> function. The parameter for the <tt>use</tt> function is a reference-to-looper - they're the same thing.

This almost looks like Recursion, but it's not. In Recursion a function calls itself. The <tt>use</tt> is not calling itself anywhere in this example.

Just a personal observation about Listing 8.6. I view this as a very confusing example simply because it uses the <tt>use</tt> function as its own argument. It would have been easier to see this work had there been another, different, function in the code that used the return value of the <tt>use</tt> function as an argument, but that's just my opinion.

Function Polymorphism (Function Overloading)
This section is pretty good at explaining this subject so I don't have anything to add, except to make sure you notice the note on page 325, What Is Name Decoration. In my travels into newsgroups and web sites, I've seen a lot of "Foo", and the mention of "name mangling". I was rather confused by all this, what were these geeks talking about. Well this particular note provides a peek into both. Try to remember this bit of info because you will see and hear a lot more of this, especially "name mangling" and the reasons for recompiling source code.

Templates
NOTE: It appears that <tt>typename</tt> cannot be used with OpenWatcom, we have to use the word <tt>class</tt> in Template declarations and definitions.

Templates is a pretty slick C++ feature. Depending on the program, these could save quite a bit of typing for the programmer as it lets the compiler do some coding for us.

The next few chapter subsections really get into to details, that to me, looks like a power programmer would be using. So I'm not going to get into it too much. For me, once I have some programming under my belt, then I might get into finding ways to really make my code super efficient, but for a beginner, this amount of detail can cause learning problems. Understanding the basics of Templates is really great, but for now, getting into such detail beyond the basic operation of Templates just isn't worth the effort right now. Once again, this is just my personal view. You all have the same book I do, so if you wish to really get into more detail, by all means do so.

Explicit Specialization
NOTE: OpenWatcom presently does not support this feature of C++. Listing 8.11, twoswap.cpp, will have to use the modifications shown on page 335. However, there is a coding error. The following: void Swap(int &n, int &m);  //regular prototype has the wrong argument types. Instead of <tt>int</tt>, use <tt>job</tt> as the type. Actually, this declaration isn't actually needed. The compiler will use the template: template  void Swap(any &a, any &b); to accomplish the task. Just comment out the line: void Swap(job & n, job & m); //regular prototype recompile and the program runs fine.

That's all for this lesson. The next lesson will finally get into Objects and Classes in Chapter 10.