[[Programming#Section 1 Foundation|Learn Programming Section 1]] previous: [[Conditions]] --- ## What are Functions All programs are made up of collections of functions. You could possibly do everything in main but why make things harder for no reason. ### Function Format ```cpp return_type function_name( parameters ); //declaration/prototype return_type function_name( parameters ) //implementation { statements.. return type; } ``` Most of the time you will be declaring and defining functions in separate places. This could be in one or multiple files. The declaration will go into a header file if you want that function to be visible to other files or in the cpp file if you want to keep it hidden. You can skip using a declaration but then only functions declared after it will be able to call it. using a simple function ```cpp int sum(int a, int b); //declaration/prototype int main() { int x = sum(5,10); return 0; } int sum (int a, int b) //implementation { return a + b; } ``` #### Default Arguments When calling a function you must fill out all parameters. ```cpp int x = sum(5); //error ``` You can however define default arguments. The only rule to that being the default parameters go last. ```cpp //this is fine int sum(int a, int b = 0) { return a + b; } //this is also fine int sum(int a = 0, int b=0) { return a + b; } //this is not int sum(int a = 0, int b) { return a + b; } ``` #### Passing Arguments When you call a function and pass in the parameters it makes a copy of those values to use. This is called pass by value. ```cpp int foo(int x) //declaring and implementing in place { return x + 10; } int main { int y = 5; // y is 5 int z = foo(y);// value of y is passed in, y remains unchanged, z is assigned a value of 15 } ``` Instead if we want our function to change our value we can use pass by reference. To do this we change the parameter to take a reference to an int. ```cpp void foo(int& x) //& means a reference { x += 10; } int main { int y = 5; // y is 5 foo(y);// y is passed in, y becomes 15 //One limitation to pass by ref is you cannot pass in straight values. foo(5); // error return 0; } ``` #### Return void is used when a function does not return anything. ```cpp void foo() { statements; //no return statement } ``` A function can have multiple return statements so long as all paths return. ```cpp int foo(int x){ //note the order of the conditions matters for the returned value; if (expression1) return 1; if (expression2) return 2; return 0; //if this return was missing you could run into errors } ``` You also need to return the correct type. Sometimes the type can be converted but this is not something you should rely on. ```cpp float foo() { return; // warning/error return 1; // warning int is converted to float return 'helloworld'; // error wrong type } void bar() { return 1.0f; // warning return float on void return; //this one is fine } ``` ### Example Functions help divide work into more manageable bites. It also allows you to easily reuse code. Lets say we want to check for the collision of 2 moving spheres. We will want a function to update the position over time and a function to check for collision. ```cpp //pseudocode struct Sphere { vec3 velocity; vec3 position; float radius; } void UpdateSphere(Sphere& sphere){ sphere.position += sphere.velocity; //sphere.velocity += acceleration; //maybe your spheres also have acceleration too sphere.velocity *= dragForce; } bool SphereCollisionTest(Sphere& a, Sphere& b) { //find distance between center points const vec3 relativePosition = a.position - b.position; const float distance = relativePosition.magnitude(); const float combinedRadius = a.radius + b.radius; //if distance is less than or equal the combined radius they are colliding if ( distance <= combinedRadius ) return true; return false; } void HandleCollision(...); int main() { //create our 2 spheres Sphere sphere1; Sphere sphere2; //set sphere position, velocity, and radius ... //update loop bool running = true; while(running) { UpdateSphere(sphere1); UpdateSphere(sphere2); if( SphereCollisionTest (sphere1, sphere2) ) HandleCollision(...); etc... } return 0; } ``` These functions are simplified a lot. If the spheres are fast enough here they could potentially teleport past each other. You also might want the collision check to tell you at what point the spheres meet. That point could then be used by the collision handling function. --- next: [[Scope Lifetime]]