Tuesday, December 9, 2008

Week 1, Day 5

I had to fight paint fumes last night, so I escaped my workspace and let the headache subside. Finished the lesson up this morning.

Today's "Class"
Functions are pretty straight forward in C++. The one new piece of code, for me, is that you have to declare a "prototype" of the function. The prototype is just a quick line of code that tells the compiler what value your function returns, the function name, and the type of variables you pass into your function (as well as any default values FOR those variables).
Sample function prototype:
int rectangleArea ( int length, int width );
You could also write it:
int rectangleArea ( int, int );
Adding the extra values of variable names though helps in the debugging process (or so the book says). You can use different parameter names than the actual defined function though... so just label it something useful if you are going to add parameter names. To add default values you would have the prototype look something like this:
int rectangleArea ( int length, int width = 10 );
This means you COULD pass one argument when you call this function and it would assume the width was 10 in that case. Obviously, you cannot have a default value for length if it (a) comes before width in the prototype and definition and (b) width does not have a default value also.

You define a function in a fairly straightforward manner. You have a header to the function with the return type, function name, and parameter list (almost identical to the prototype, except that the parameters MUST have names in the function header and you can't add default values in the header).
Here is the rectangleArea function definition:
int rectangleArea ( int rectangleLength, int rectangleWidth )
{
return (rectangleLength * rectangleWidth);
}


Super easy right? Now the chapter went into some interesting details about what you can do with functions in C++.

Function Overloading
Because you have to define the return value and the variable types of the parameters... what happens when you pass in a float instead of an int. Yep, it creates an error. However, in C++ you CAN use identical function names as long as they return and / or accept different variable types. Like this:

int Double ( int );
float Double ( float );

int Double ( int x )
{
return (x * 2);
}

float Double ( float x )
{
return (x * 2);
}


This way, if you call the function Double with either an integer or a float it still returns the value you want it to. You don't need to have two differently named functions and then have to remember which function you needed to call. You can "overload" a function many, many times (say you want to double short, long, float, double, and maybe even some signed and unsigned variables as well...). The book did mention you have to be careful with doing something like this:

int Divide ( int x, int y = 2 );
int Divide ( int x );

int Divide ( int x, int y )
{
return (x / y);
}

int Divide ( int x )
{
return (x / 3);
}


As you can imagine, if you DO make this function call "Divide(myVariable)", the compiler won't know which function you actually want to call and will throw up an error.

Inline Functions
Another feature in C++ is the ability to add a function "inline" the code when it is called. This can give you some performance gain... but at a cost. Every time you call that function, it will add the entire function body into your code and thus take up more storage on the hard drive, CD, etc. The book recommended you only use inline functions when the function is one or two lines as larger functions tend to bloat your code and the performance is probably negated by the extra code size. How much of a benefit you get by doing inline functions... I know not. Maybe I should play around and do some benchmarking... as soon as I know how to benchmark C++ code at least.
Here is how you have a function inline. In the function prototype declaration, you simply add the keyword "inline" before the return type. Here is an example:
inline int Divide ( int x, int y );

Recursive Functions
You can have a function call itself... or you can have a function call another function, which happens to call the first funciton again...
Confusing? Perhaps, that wasn't the best explanation. The danger is if you don't have a condition to the function that is being recurringly called. If the function just continues to call itself indefinitely it will bloat your program in your RAM until it crashes.
Why would you want to use Recursive functions? The book had a couple of examples of ways to use recursive functions, but I don't see why you would need to do them with those examples. In PHP or PERL you could easily do a FOR loop and take care of their examples without adding more and more to the RAM. However the book did mention there are the occasional problems that recursive functions are an elegant answer for. When I find one, I will no doubt be happy I know how to do recursive functions (or at least know where to look up so I can remember... although the implementation is exactly what you think it is... you just call the function from within the same function or another called function...).

Summary and Workshop
In the exercises there were some "bug finding" programs where you had to figure out what was wrong. Some of the bugs are things I'm sure programmers do ALL THE TIME. Like accidentally typing a semicolon after function header (in the definition... not after the prototype, which is required). I caught myself doing that a few times... but I caught it write after I typed it, so it wasn't a big deal. If I wasn't paying too much attention though I could see that causing some irritation. One of the exercises was to do a recursive function that solved x to the power of n sort of math problems (like x squared... x ^ 8... etc). That one made me think. Took me back to middle school when we had to do that sort of stuff all the time. Or was that High School... *shrug* whatever, either way it was a while ago. I ended up getting it first try though, so at least I had that going for me.

No comments: