Unit 06: Functions

  1. What is a function?
  2. Function signature
  3. Function DECLARATIONS and DEFINITIONS 1
  4. Function DECLARATIONS and DEFINITIONS 2
  5. Function DECLARATIONS and DEFINITIONS 3
  6. Calling functions
  7. Arguments vs. Parameters
  8. Scope 1
  9. Scope 2
  10. Scope 3

  11. Example code and additional resources

This week's stuff:

Functions

What is a function?

Functions are a handy way for us to split out some code from our main() function, giving that code a name (the function name) to identify it. When we do this, we make very modular programs where it is easier to maintain because everything is broken up into distinct, discrete steps. In math, a function looks like this:

f(x) = 2x+1

Where f is the function name, x is the input, and whatever is computed on the right-hand-side of the equal sign is the return output.

It's the same in programming: Our functions can have inputs, process some data, and return some outputs. And, because they're defined elseware in the program, we can call them as many times as we want.

Function signature

A function signature in C++ is required as part of both the function declaration and the definition. The signature is how you tell functions apart - what makes them unique... their signature.

The function signature takes this form:

RETURN_TYPE FUNCTION_NAME( PARAM1TYPE PARAM1NAME, PARAM2TYPE PARAM2NAME, ... )


So for instance, a GetArea function signature could look like this:

float GetArea( float width, float length )

Function DECLARATIONS and DEFINITIONS

When we want to create a function we need to write a function declaration and a function definition.

The function declaration is the function signature and a ; at the end. Declarations should go in header (.h) files.

int Func( int a, int b );

The definition includes the function signature but also a code block - denoted by opening and closing curly braces { }. Within this code block is where we define what the function does.

int Func( int a, int b )
{
   return a * b + 1;
}

Function DECLARATIONS and DEFINITIONS 2

When we create a header file, it should end with .h, though sometimes ends with .hpp (depending on the programmer's style.)

The header must contain file guards:

#ifndef _MY_FILE_H
#define _MY_FILE_H

// put code in here

#endif
You can use any label to replace "_MY_FILE_H", but it should be unique for each file. The file guard prevents the compiler from reading the same code multiple times, and essentially thinking that you've written a bunch of duplicate code. Within the header file we put our function declarations:
#ifndef _MY_FILE_H
#define _MY_FILE_H

#include <string>
using namespace std;

string GetState( int zipcode );
char GetCurrencyType( string country );
float Quadratic1( float a, float b, float c );
float Quadratic2( float a, float b, float c );

#endif
If any of our function signatures have special data types like string we need to make sure to also include the appropriate library in the file as well.

Function DECLARATIONS and DEFINITIONS 3

Function definitions should go in source files (.cpp files). Usually, there should be one source file for main(), and a separate source file for function definitions, based on some grouping.

If you were splitting out reusable functions for doing math, you could create something like "Math.h" and "Math.cpp" to store those functions' declarations and definitions.

The .cpp files don't need file guards, but you do need to include the corresponding header file that contains the functions' declarations. In Math.cpp you'd need:

#include "Math.h"

As a program grows, you might have many different sets of files, so it's good to group things by similar functionality.

Calling functions

The third piece is the function call, when we are actually putting it into use in our code. The function call occurs from outside of the function, such as within main() (or, one function can call another function!)

The function call is of this form:

FunctionName( arg1, arg2, arg3 );
Or, if the function returns data, we need to make sure to put the result somewhere. The data type of the variable you use to store the result should match the function's return type:
float result = Sum( 2, 4 );
We can pass hard-coded literals in as the input, or we can pass in existing variables as the inputs.
float num1 = 3;
float num2 = 5;
float result = Sum( num1, num2 ); // Two variables
float result2 = Sum( 1, 3 ); // Two int literals
float result3 = Sum( num1, 3 ); // A variable and a literal

Arguments vs. Parameters

Another key piece of terminology is parameters versus arguments.

When we're declaring or defining a function and we have input variables in the signature, like this:

float Sum( float a, float b );
Those two input variables a and b are known as parameters. When we're creating the function, we define the input parameters.

When we're calling the function and passing in data - whether as a literal or a variable's data, like this:
float result = Sum( 1, 2 );
float result = Sum( myNum1, myNum2 );
The data being passed as input are called arguments.

Scope

Variables have different life times. Where they exist in the program is known as its scope. A variable lives within the code block { } it is declared within, and does not exist outside of it.

For example, this variable totalCats will exist all throughout main():

int main()
{
  int totalCats = 10;
  // ...
}
And the variable quotient only exists within this if statement:
int main()
{
  float num = 3, denom = 4;

  if ( denom != 0 )
  {
    float quotient = num / denom;
  }

  // ...
  return 0;
}

Scope 2

Variables can be used within code blocks that are inside their own code block and beneath where the variable is declared. Here, a can be used anywhere in main(), including in the if statement. b, however, can only be used within main() anywhere after its declaration. c can only be used inside the if statement it was declared within:

int main()
{
  int a = 1;

  if ( a < 0 )
  {
    int c = -a;
  }

  int b = 2;
  cout << b << endl;

  // ...
  return 0;
}

Scope 3

Just like how a variable declared at the top of main() will exist throughout main(), the same is true for functions. If we declare a variable at the top, we can use it throughout the entire function - and, we can use the function's parameters anywhere within the function.

But variables don't exist between functions. Something declared in one function cannot be used in another function. Variable names can, however, be reused in different scopes.

Example code and additional resources

Example code: (repository)

Videos: