RoboCatz.com
About FLL | Navigation | Playbook | Strategy | Models | Techniques | RobotC | Programming | Robot News |

Playbook: Function Overloading

Definition: The ability to define multiple functions with the same name but with different implementations.

driveForward();   // Just start driving forward
driveForward(12); // Just drive for 12 inches
driveForward(12,25); // Drive for 12 inches at 25% power
The types of function overloading we use are classified as a form of static polymorphism in which a function call is resolved using the 'best match technique', i.e., the function is resolved depending upon the argument list.

Function overloading is usually associated with statically-typed programming languages which enforce type checking in function calls. When overloading a function, you are really just making a number of different functions that happen to have the same name. When the program is "compiled", the compiler determines which of the functions are used in each instance.

Default Values vs Passed Values

A function defined without parameters will typically use the default parameters. For example, if you do not specify a power level for the motors, the default (or current) power level will be used.

If you examine the following code, you will see two instances of the driveForward() function. One has the distance specified while the other has the distance AND power level specified.

task main() {
  driveForward(12);
  driveForward(12, 35);
}
Both of these functions will make the robot drive forward 12 inches. But the first one does so at the default power level and the second one does it at the specified power level.

Let's examine the inner workings of these two commands to see how the default power level is used (or not used). To accomplish this, there are two separate definitions of the function. See below.

// Declare a global variable for the defaultPowerLevel
int defaultPowerLevel=20;

// Define three driveForward() functions
// First driveForward() definition includes distance and power as passed parameters (arguments)
void driveForward(int distance, int powerLevel) {
  forward(distance*30, degrees, powerLevel);
}

// The second driveForward() function is defined to only use the distance parameter
//   The defaultPowerLevel is added inside the function to ANOTHER call
//   to the driveForward() function.  Only the one inside uses both parameters.
void driveForward(int distance) {
  driveForward(distance, defaultPowerLevel);
}

// The third driveForward() function is defined without passing any parameters
// Inside this function, motors B and C are set to the default power level.
void driveForward() {
  setMultipleMotors(defaultPowerLevel, B, C);
}

task main() {
  driveForward(12);
  driveForward(12, 35);

  driveForward();
  untilDistance(12);
  stopMoving();
}

driveForward() vs. driveForward(12)

When should you use driveForward()? And when should you use driveForward(12)?
The easy answer would be to just say: "it depends on what you want to do". Clearly the driveForward(12); will tell the robot to drive forward for 12 inches and stop.

If you use driveForward(), you have to follow up that function with something that tells the robot look for a certain condition such as the following examples:

// Declare a global variable for the defaultPowerLevel
int defaultPowerLevel=20;
void driveForward(int distance, int powerLevel) { forward(distance*30, degrees, powerLevel); }
void driveForward(int distance) { driveForward(distance, defaultPowerLevel); }
void driveForward() { setMultipleMotors(defaultPowerLevel, B, C); }
#define stopOnTouch() while(!SensorValue[touchSensor]) sleep(5); stopMoving()

task main() {
  driveForward();  // Tells the robot to drive forward
  untilLine();     //   until it sees a black line
  stopMoving();    //   and then stop moving.

  driveForward();  // Tells the robot to drive forward
  untilTouch();    //   until it bumps into the wall
  stopMoving();    //   and then stop moving.

  driveForward();  // Tells the robot to drive forward
  stopOnTouch();   //   and then stop moving when it touches the wall.

}

Exercise 1 (Difficulty level: Intermediate)

Exercise 1: Demonstrate that you understand function overloading by creating three different forms (i.e. polymorphism) of the driveBackward() function.
Hint: You will need to create three definitions of the function before the main task. Each definition will have the same function name. However, each definition will have a different combination of parameters.


Exercise 2 (Difficulty level: Expert)

The RobotC language includes a native function for drawing circles on the LCD panel. This function is:
drawCircle(CenterX, CenterY, Radius)
Create multiple forms of this function such that:

circle(x, y, r); // draws a circle at position x, y with radius r

circle(x, y); // draws a randomly sized circle at the specified location

circle(r); // draws a circle with a specified radius at a random position on the LCD screen

circle(); // draws a circle with a random radius at a random position on the LCD screen
Hint:

// To draw a circle at a random location...
#define random(Limit) abs(rand()%Limit)
void circle(int radius) {
  int x=random(100);
  int y=random(100);
  drawCircle(x, y, radius);
}
Exercise (exercise-in-function-overloading.htm)
This is an exercise with numerous examples in robotC code. This exercise covers function overloading and multi threaded programs.