Characters
A char variable holds a 1-byte integer. However, instead of interpreting the value of the char as an integer, the value of a char variable is typically interpreted as an ASCII character.
A character is enclosed between single quotes (such as 'a', 'b', etc). For example: char test = 'S';
American Standard Code for Information Interchange (ASCII) is a character-encoding scheme that is used to represent text in computers. ------------------------------------------------------------------------------------------------- Booleans
Boolean variables only have two possible values: true (1) and false (0). To declare a boolean variable, we use the keyword bool.
bool online = false; bool logged_in = true;
If a Boolean value is assigned to an integer, true becomes 1 and false becomes 0. If an integer value is assigned to a Boolean, 0 becomes false and any value that has a non-zero value becomes true. ------------------------------------------------------------------------------------------------- Variable Naming Rules
Use the following rules when naming variables: - All variable names must begin with a letter of the alphabet or an underscore( _ ). - After the initial letter, variable names can contain additional letters, as well as numbers. Blank spaces or special characters are not allowed in variable names. There are two known naming conventions: Pascal case: The first letter in the identifier and the first letter of each subsequent concatenated word are capitalized. For example: BackColor Camel case: The first letter of an identifier is lowercase and the first letter of each subsequent concatenated word is capitalized. For example: backColor ------------------------------------------------------------------------------------------------ Case-Sensitivity
C++ is case-sensitive, which means that an identifier written in uppercase is not equivalent to another one with the same name in lowercase. For example, myvariable is not the same as MYVARIABLE and not the same as MyVariable. These are three different variables. Choose variable names that suggest the usage, for example: firstName, lastName. ------------------------------------------------------------------------------------------------ Variable Naming Rules
C++ keyword (reserved word) cannot be used as variable names. For example, int, float, double, cout cannot be used as a variable name. There is no real limit on the length of the variable name (depends on the environment), but try to keep your variable names practical and meaningful. ------------------------------------------------------------------------------------------------- Arrays
An array is used to store a collection of data, but it may be useful to think of an array as a collection of variables that are all of the same type. Instead of declaring multiple variables and storing individual values, you can declare a single array to store all the values. When declaring an array, specify its element types, as well as the number of elements it will hold. For example:
int a[5];
In the example above, variable a was declared as an array of five integer values [specified in square brackets]. You can initialize the array by specifying the values it holds:
int b[5] = {11, 45, 62, 70, 88};
The values are provided in a comma separated list, enclosed in {curly braces}. The number of values between braces { } must not exceed the number of the elements declared within the square brackets [ ]. -------------------------------------------------------------------------------------------------- Initializing Arrays
If you omit the size of the array, an array just big enough to hold the initialization is created. For example: int b[] = {11, 45, 62, 70, 88};
This creates an identical array to the one created in the previous example.
Each element, or member, of the array has an index, which pinpoints the element's specific position. The array's first member has the index of 0, the second has the index of 1. To access array elements, index the array name by placing the element's index in square brackets following the array name. For example:
int b[] = {11, 45, 62, 70, 88};
cout << b[0] << endl; // Outputs 11
cout<< b[3] << endl; // Outputs 70 ------------------------------------------------------------------------------------------------- Accessing Array Elements
Index numbers may also be used to assign a new value to an element. int b[] = {11, 45, 62, 70, 88}; b[2] = 42; This assigns a value of 42 to the array's third element. Always remember that the list of elements always begins with the index of 0. -------------------------------------------------------------------------------------------------- Arrays in Loops
It's occasionally necessary to iterate over the elements of an array, assigning the elements values based on certain calculations. Usually, this is accomplished using a loop. -------------------------------------------------------------------------------------------------- Arrays in Loops
Let's declare an array, that is going to store 5 integers, and assign a value to each element using the for loop:
int myArr[5];
for(int x=0; x<5; x++) { myArr[x] = 42; }
Each element in the array is assigned the value of 42. The x variable in the for loop is used as the index for the array. The last index in the array is 4, so the for loop condition is x<5. ------------------------------------------------------------------------------------------------- Arrays in Loops
Let's output each index and corresponding value in the array.
int myArr[5]; for(int x=0; x<5; x++) { myArr[x] = 42; cout << x << ": " << myArr[x] << endl; }
/* Outputs 0: 42 1: 42 2: 42 3: 42 4: 42 */ ------------------------------------------------------------------------------------------------ Arrays in Calculations
The following code creates a program that uses a for loop to calculate the sum of all elements of an array.
int arr[] = {11, 35, 62, 555, 989}; int sum = 0; for (int x = 0; x < 5; x++) { sum += arr[x]; } cout << sum << endl; //Outputs 1652
To review, we declared an array and a variable sum that will hold the sum of the elements. Next, we utilized a for loop to iterate through each element of the array, and added the corresponding element's value to our sum variable. In the array, the first element's index is 0, so the for loop initializes the x variable to 0. ------------------------------------------------------------------------------------------------- Multi-Dimensional Arrays
A multi-dimensional array holds one or more arrays. Declare a multidimensional array as follows. type name[size1][size2]...[sizeN];
Here, we've created a two-dimensional 3x4 integer array: int x[3][4];
Visualize this array as a table composed of 3 rows, and 4 columns. -------------------------------------------------------------------------------------------------- Two-Dimensional Arrays
Multi-dimensional arrays may be initialized by specifying bracketed values for each row. Following is an array with 2 rows and 3 columns: int x[2][3] = { {2, 3, 4}, // 1st row {8, 9, 10} // 2nd row };
You can also write the same initialization using just one row. int x[2][3] = {{2, 3, 4}, {8, 9, 10}};
The elements are accessed by using the row index and column index of the array. For example: int x[2][3] = {{2, 3, 4}, {8, 9, 10}}; cout << x[0][2] << endl;
//Outputs 4
The first index 0 refers to the first row. The second index 2 refers to the 3rd element of the first row, which is 4. -------------------------------------------------------------------------------------------------- Multi-Dimensional Arrays
Arrays can contain an unlimited number of dimensions. string threeD[42][8][3];
The example above declares a three-dimensional array of strings. As we did previously, it's possible to use index numbers to access and modify the elements. Arrays more than three dimensions are harder to manage. -------------------------------------------------------------------------------------------------- Pointers
Every variable is a memory location, which has its address defined. That address can be accessed using the ampersand (&) operator (also called the address-of operator), which denotes an address in memory. For example:
int score = 5; cout << &score << endl;
//Outputs "0x29fee8"
This outputs the memory address, which stores the variable score. ------------------------------------------------------------------------------------------------- Pointers
A pointer is a variable, with the address of another variable as its value. In C++, pointers help make certain tasks easier to perform. Other tasks, such as dynamic memory allocation, cannot be performed without using pointers.
All pointers share the same data type - a long hexadecimal number that represents a memory address. The only difference between pointers of different data types is the data type of the variable that the pointer points to. ------------------------------------------------------------------------------------------------- Pointers
A pointer is a variable, and like any other variable, it must be declared before you can work with it. The asterisk sign is used to declare a pointer (the same asterisk that you use for multiplication), however, in this statement the asterisk is being used to designate a variable as a pointer.
Following are valid pointer declarations: int *ip; // pointer to an integer double *dp; // pointer to a double float *fp; // pointer to a float char *ch; // pointer to a character
Just like with variables, we give the pointers a name and define the type, to which the pointer points to. The asterisk sign can be placed next to the data type, or the variable name, or in the middle. -------------------------------------------------------------------------------------------------- Using Pointers
Here, we assign the address of a variable to the pointer.
int score = 5; int *scorePtr; scorePtr = &score;
cout << scorePtr << endl;
//Outputs "0x29fee8"
The code above declares a pointer to an integer called scorePtr, and assigns to it the memory location of the score variable using the ampersand (address-of) operator. Now, scorePtr's value is the memory location of score. -------------------------------------------------------------------------------------------------- Pointer Operations
There are two operators for pointers: Address-of operator (&): returns the memory address of its operand. Contents-of (or dereference) operator (*): returns the value of the variable located at the address specified by its operand.
For example:
int var = 50; int *p; p = &var;
cout << var << endl; // Outputs 50 (the value of var)
cout << p << endl; // Outputs 0x29fee8 (var's memory location)
cout << *p << endl; /* Outputs 50 (the value of the variable stored in the pointer p) */
The asterisk (*) is used in declaring a pointer for the simple purpose of indicating that it is a pointer (The asterisk is part of its type compound specifier). Don't confuse this with the dereference operator, which is used to obtain the value located at the specified address. They are simply two different things represented with the same sign. ------------------------------------------------------------------------------------------------- Dereferencing
The dereference operator (*) is basically an alias for the variable the pointer points to. For example:
int x = 5; int *p = &x;
x = x + 4; x = *p + 4; *p = *p + 4;
All three of the preceding statements are equivalent, and return the same result. We can access the variable by dereferencing the variable's pointer. As p is pointing to the variable x, dereferencing the pointer (*p) is representing exactly the same as the variable x. -------------------------------------------------------------------------------------- Static & Dynamic Memory
To be successful as a C++ programmer, it's essential to have a good understanding of how dynamic memory works. In a C++ program, memory is divided into two parts: The stack: All of your local variables take up memory from the stack. The heap: Unused program memory that can be used when the program runs to dynamically allocate the memory. Many times, you are not aware in advance how much memory you will need to store particular information in a defined variable and the size of required memory can be determined at run time. You can allocate memory at run time within the heap for the variable of a given type using the new operator, which returns the address of the space allocated.
new int;
This allocates the memory size necessary for storing an integer on the heap, and returns that address. --------------------------------------------------------------------------------------- Dynamic Memory
The allocated address can be stored in a pointer, which can then be dereferenced to access the variable. Example:
int *p = new int; *p = 5;
We have dynamically allocated memory for an integer, and assigned it a value of 5. The pointer p is stored in the stack as a local variable, and holds the heap's allocated address as its value. The value of 5 is stored at that address in the heap. ---------------------------------------------------------------------------------------- Dynamic Memory
For local variables on the stack, managing memory is carried out automatically. On the heap, it's necessary to manually handle the dynamically allocated memory, and use the delete operator to free up the memory when it's no longer needed.
delete pointer;
This statement releases the memory pointed to by pointer. For example:
int *p = new int; // request memory *p = 5; // store value cout << *p << endl; // use value delete p; // free up the memory
Forgetting to free up memory that has been allocated with the new keyword will result in memory leaks, because that memory will stay allocated until the program shuts down. --------------------------------------------------------------------------------------- Dangling Pointers
The delete operator frees up the memory allocated for the variable, but does not delete the pointer itself, as the pointer is stored on the stack.
Pointers that are left pointing to non-existent memory locations are called dangling pointers. For example:
int *p = new int; // request memory *p = 5; // store value
delete p; // free up the memory // now p is a dangling pointer
p = new int; // reuse for a new address
The NULL pointer is a constant with a value of zero that is defined in several of the standard libraries, including iostream. It's a good practice to assign NULL to a pointer variable when you declare it, in case you do not have exact address to be assigned. A pointer assigned NULL is called a null pointer. For example: int *ptr = NULL; ----------------------------------------------------------------------------------------- Dynamic Memory
Dynamic memory can also be allocated for arrays. For example:
int *p = NULL; // Pointer initialized with null p = new int[20]; // Request memory delete [] p; // Delete array pointed to by p
Note the brackets in the syntax. Dynamic memory allocation is useful in many situations, such as when your program depends on input. As an example, when your program needs to read an image file, it doesn't know in advance the size of the image file and the memory necessary to store the image. ----------------------------------------------------------------------------------- sizeof
While the size allocated for varying data types depends on the architecture of the computer you use to run your programs, C++ does guarantee a minimum size for the basic data types:
The sizeof operator can be used to get a variable or data type's size, in bytes. Syntax: sizeof (data type)
The sizeof operator determines and returns the size of either a type or a variable in bytes. For example:
cout << "char: " << sizeof(char) << endl; cout << "int: " << sizeof(int) << endl; cout << "float: " << sizeof(float) << endl; cout << "double: " << sizeof(double) << endl; int var = 50; cout << "var: " << sizeof(var) << endl;
/* Outputs char: 1 int: 4 float: 4 double: 8 var: 4 */
Output values may vary, according to the computer and compiler used. -------------------------------------------------------------------------------------- Size of an Array
The C++ sizeof operator is also used to determine the size of an array. For example: double myArr[10]; cout << sizeof(myArr) << endl;
//Outputs 80
On our machine, double takes 8 bytes. The array stores 10 doubles, so the entire array occupies 80 (8*10) bytes in the memory. In addition, divide the total number of bytes in the array by the number of bytes in a single element to learn how many elements you have in the array. For example:
int numbers[100]; cout << sizeof(numbers) / sizeof(numbers[0]);
// Outputs 100 ---------------------------------------------------------------------------------------- Functions
A function is a group of statements that perform a particular task. You may define your own functions in C++.
Using functions can have many advantages, including the following: - You can reuse the code within a function. - You can easily test individual functions. - If it's necessary to make any code modifications, you can make modifications within a single function, without altering the program structure. - You can use the same function for different inputs. Every valid C++ program has at least one function - the main() function. ------------------------------------------------------------------------------------------ The Return Type
The main function takes the following general form:
int main() { // some code return 0; }
A function's return type is declared before its name. In the example above, the return type is int, which indicates that the function returns an integer value. Occasionally, a function will perform the desired operations without returning a value. Such functions are defined with the keyword void. void is a basic data type that defines a valueless state. --------------------------------------------------------------------------------------------- Defining a Function
Define a C++ function using the following syntax:
return_type function_name( parameter list ) { body of the function }
return-type: Data type of the value returned by the function. function name: Name of the function. parameters: When a function is invoked, you pass a value to the parameter. This value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the parameters of a function. body of the function: A collection of statements defining what the function does. Parameters are optional; that is, you can have a function with no parameters. ------------------------------------------------------------------------------------------------ Defining a Function
As an example, let's define a function that does not return a value, and just prints a line of text to the screen.
void printSomething() { cout << "Hi there!"; }
Our function, entitled printSomething, returns void, and has no parameters. Now, we can use our function in main().
int main() { printSomething(); return 0; }
To call a function, you simply need to pass the required parameters along with the function name. -------------------------------------------------------------------------------------------------- Functions
You must declare a function prior to calling it. For example:
#include <iostream> using namespace std; void printSomething() { cout << "Hi there!"; } int main() { printSomething(); return 0; }
Putting the declaration after the main() function results in an error. -------------------------------------------------------------------------------------------------- Functions
A function declaration, or function prototype, tells the compiler about a function name and how to call the function. The actual body of the function can be defined separately. For example:
#include <iostream> using namespace std; //Function declaration void printSomething(); int main() { printSomething(); return 0; }
//Function definition void printSomething() { cout << "Hi there!"; }
Function declaration is required when you define a function in one source file and you call that function in another file. In such case, you should declare the function at the top of the file calling the function. ------------------------------------------------------------------------------------------------- Function Parameters
For a function to use arguments, it must declare formal parameters, which are variables that accept the argument's values.
For example:
void printSomething(int x) { cout << x; }
This defines a function that takes one integer parameter and prints its value. Formal parameters behave within the function similarly to other local variables. They are created upon entering the function, and are destroyed upon exiting the function. -------------------------------------------------------------------------------------------------- Function Parameters
Once parameters have been defined, you can pass the corresponding arguments when the function is called. For example:
#include <iostream> using namespace std; void printSomething(int x) { cout << x; } int main() { printSomething(42); }
// Outputs 42 The value 42 is passed to the function as an argument, and is assigned to the formal parameter of the function: x. Making changes to the parameter within the function does not alter the argument. --------------------------------------------------------------------------------------------------- Function Parameters
You can pass different arguments to the same function. For example:
int timesTwo(int x) { return x*2; }
The function defined above takes one integer parameter and returns its value, multiplied by 2. We can now use that function with different arguments.
int main() { cout << timesTwo(8); // Outputs 16
cout <<timesTwo(5); // Outputs 10
cout <<timesTwo(42); // Outputs 84 } --------------------------------------------------------------------------------------------------- Multiple Parameters
You can define as many parameters as you want for your functions, by separating them with commas.
Let's create a simple function that returns the sum of two parameters.
int addNumbers(int x, int y) { // code goes here }
As defined, the addNumbers function takes two parameters of type int, and returns int. Data type and name should be defined for each parameter. ----------------------------------------------------------------------------------------------------- Multiple Parameters
Now let's calculate the sum of the two parameters and return the result:
int addNumbers(int x, int y) { int result = x + y; return result; } ----------------------------------------------------------------------------------------------------- Fill in the missing parts of the function addNumbers which takes two integer variables x and y, and returns their sum. Sum is calculated and stored in the 'answer' variable. int addNumbers(int x, int y) { int answer = x + y; return answer; } ------------------------------------------------------------------------------------------------------- Multiple Parameters
Now we can call the function.
int addNumbers(int x, int y) { int result = x + y; return result; }
int main() { cout << addNumbers(50, 25); // Outputs 75 }
You can also assign the returned value to a variable. int main() { int x = addNumbers(35, 7); cout << x; // Outputs 42 } ---------------------------------------------------------------------------------------------------------- Multiple Parameters
You can add as many parameters to a single function as you want. For example:
int addNumbers(int x, int y, int z, int a) { int result = x + y + z + a; return result; }
If you have multiple parameters, remember to separate them with commas, both when declaring them and when passing the arguments. ----------------------------------------------------------------------------------------------------------- Random Numbers
Being able to generate random numbers is helpful in a number of situations, including when creating games, statistical modeling programs, and similar end products.
In the C++ standard library, you can access a pseudo random number generator function that's called rand(). When used, we are required to include the header <cstdlib>.
#include <iostream> #include <cstdlib> using namespace std; int main() { cout << rand(); }
This will output a random number. ------------------------------------------------------------------------------------------------------------ Random Numbers
A for loop can be used to generate multiple random numbers.
int main() { for (int x = 1; x <= 10; x++) { cout << rand() << endl; } }
/* Output: 41 18467 6334 26500 19169 15724 11478 29358 26962 24464 */ ------------------------------------------------------------------------------------------------------------ Random Numbers
Use the modulo (%) operator to generate random numbers within a specific range. The example below generates whole numbers within a range of 1 to 6.
int main () { for (int x = 1; x <= 10; x++) { cout << 1 + (rand() % 6) << endl; } }
/* Output: 6 6 5 5 6 5 1 1 5 3 */
However, the rand() function will only return a pseudo random number. This means that each time the code is run, it generates the same numbers. ----------------------------------------------------------------------------------------------------------- The srand() Function
The srand() function is used to generate truly random numbers. This function allows to specify a seed value as its parameter, which is used for the rand() function's algorithm.
int main () { srand(98);
for (int x = 1; x <= 10; x++) { cout << 1 + (rand() % 6) << endl; } }
Changing the seed value changes the return of rand(). However, the same argument will result in the same output. ------------------------------------------------------------------------------------------------------------ Truly Random Numbers
A solution to generate truly random numbers, is to use the current time as a seed value for the srand() function. This example makes use of the time() function to get the number of seconds on your system time, and randomly seed the rand() function (we need to include the <ctime> header for it):
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main () { srand(time(0)); for (int x = 1; x <= 10; x++) { cout << 1 + (rand() % 6) << endl; } }
time(0) will return the current second count, prompting the srand() function to set a different seed for the rand() function each time the program runs. Using this seed value will create a different output each time we run the program. ------------------------------------------------------------------------------------------------------------ Default Values for Parameters
When defining a function, you can specify a default value for each of the last parameters. If the corresponding argument is missing when you call a function, it uses the default value.
To do this, use the assignment operator to assign values to the arguments in the function definition, as shown in this example.
int sum(int a, int b=42) { int result = a + b; return (result); }
This assigns a default value of 42 to the b parameter. If we call the function without passing the value for the b parameter, the default value will be used.
int main() { int x = 24; int y = 36;
//calling the function with both parameters int result = sum(x, y); cout << result << endl; //Outputs 60
//calling the function without b result = sum(x); cout << result << endl; //Outputs 66
return 0; }
The second call to the function does not pass a value for the second parameter, and the default value of 42 is used, instead. ---------------------------------------------------------------------------------------------------- Using Default Arguments
Another example: int volume(int l=1, int w=1, int h=1) { return l*w*h; }
int main() { cout << volume() << endl; cout << volume(5) << endl; cout << volume(2, 3) << endl; cout << volume(3, 7, 6) << endl; }
/* Output 1 5 6 126 */
As you can see, default parameter values can be used for calling the same function in different situations, when one or more of its parameters are not used. ---------------------------------------------------------------------------------------------------- Overloading
Function overloading allows to create multiple functions with the same name, so long as they have different parameters. For example, you might need a printNumber() function that prints the value of its parameter.
void printNumber(int a) { cout << a; }
This is effective with integer arguments only. Overloading it will make it available for other types, such as floats.
void printNumber(float a) { cout << a; }
Now, the same printNumber() function name will work for both integers and floats. ----------------------------------------------------------------------------------------------------- Function Overloading
When overloading functions, the definition of the function must differ from each other by the types and/or the number of arguments in the argument list. For example:
void printNumber(int x) { cout << "Prints an integer: " << x << endl; } void printNumber(float x) { cout << "Prints a float: " << x << endl; } int main() { int a = 16; float b = 54.541; printNumber(a); printNumber(b); }
/* Output: Prints an integer: 16 Prints a float: 54.541 */
As you can see, the function call is based on the argument provided. An integer argument will call the function implementation that takes an integer parameter. A float argument will call the implementation taking a float parameter. -------------------------------------------------------------------------------------------------------- Function Overloading
You can not overload function declarations that differ only by return type. The following declaration results in an error.
int printName(int a) { } float printName(int b) { } double printName(int c) { }
Although each function uses the same name, the only difference from one to the other is the return type, which is not allowed. --------------------------------------------------------------------------------------------------------- Recursion
A recursive function in C++ is a function that calls itself.
To avoid having the recursion run indefinitely, you must include a termination condition. --------------------------------------------------------------------------------------------------------- Recursion
To demonstrate recursion, let's create a program to calculate a number's factorial. In mathematics, the term factorial refers to the product of all positive integers that are less than or equal to a specific non-negative integer (n). The factorial of n is denoted as n! For example:
4! = 4 * 3 * 2 * 1 = 24 ---------------------------------------------------------------------------------------------------------- Recursion
Let's define our function:
int factorial(int n) { if (n==1) { return 1; } else { return n * factorial(n-1); } }
The if statement defines the exit condition. In this case, it's when n equals one, return 1 (the factorial of one is one). We placed the recursive function call in the else statement, which returns n multiplied by the factorial of n-1. For example, if you call the factorial function with the argument 4, it will execute as follows: return 4 * factorial(3), which is 4*3*factorial(2), which is 4*3*2*factorial(1), which is 4*3*2*1. The factorial function calls itself, and then continues to do so, until the argument equals 1. ----------------------------------------------------------------------------------------------------------- Recursion
We're now at the point where we can call our factorial function.
int factorial(int n) { if (n==1) { return 1; } else { return n * factorial(n-1); } } int main() { cout << factorial(5); }
//Outputs 120
Another name for the exit condition is the base case. Keep in mind that a base case is necessary for real recursion. Without it, the recursion will keep running forever. ------------------------------------------------------------------------------------------------------------- Arrays and Functions
An array can also be passed to a function as an argument. The parameter should be defined as an array using square brackets, when declaring the function. For example:
void printArray(int arr[], int size) { for(int x=0; x<size; x++) { cout <<arr[x]; } } -------------------------------------------------------------------------------------------------------------- Arrays and Functions
We can use our function in main(), and call it for our sample array:
void printArray(int arr[], int size) { for(int x=0; x<size; x++) { cout <<arr[x]<< endl; } } int main() { int myArr[3]= {42, 33, 88}; printArray(myArr, 3); }
The printArray function takes an array as its parameter (int arr[]), and iterates over the array using a for loop. We call the function in main(), which is where we pass the myArr array to the function, which prints its elements. Remember to specify the array's name without square brackets when passing it as an argument to a function. ---------------------------------------------------------------------------------------------------------------- Function Arguments
There are two ways to pass arguments to a function as the function is being called. By value: This method copies the argument's actual value into the function's formal parameter. Here, we can make changes to the parameter within the function without having any effect on the argument. By reference: This method copies the argument's reference into the formal parameter. Within the function, the reference is used to access the actual argument used in the call. This means that any change made to the parameter affects the argument. By default, C++ uses call by value to pass arguments. ------------------------------------------------------------------------------------------------------------------- Passing by Value
By default, arguments in C++ are passed by value. When passed by value, a copy of the argument is passed to the function. Example:
void myFunc(int x) { x = 100; } int main() { int var = 20; myFunc(var); cout << var; } // Outputs 20 Try It Yourself
Because a copy of the argument is passed to the function, the original argument is not modified by the function. --------------------------------------------------------------------------------------------------------------------- Passing by Reference
Pass-by-reference copies an argument's address into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. This means that changes made to the parameter affect the argument. To pass the value by reference, argument pointers are passed to the functions just like any other value.
void myFunc(int *x) { *x = 100; } int main() { int var = 20; myFunc(&var); cout << var; } // Outputs 100
As you can see, we passed the variable directly to the function using the address-of operator &. The function declaration says that the function takes a pointer as its parameter (defined using the * operator). As a result, the function has actually changed the argument's value, as accessed it via the pointer. --------------------------------------------------------------------------------------------------------------------- Fill in the blanks to pass the variable arg by value to the 'passByValue' function: void passByValue(int x) { x = 99;} int main() { int arg = 13; passByValue(arg); return 0; } ------------------------------------------------------------------------------------------------------ Summary
Passing by value: This method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument. Passing by reference: This method copies the reference of an argument into the formal parameter. Inside the function, the reference is used to access the actual argument used in the call. So, changes made to the parameter also affect the argument. In general, passing by value is faster and more effective. Pass by reference when your function needs to modify the argument, or when you need to pass a data type, that uses a lot of memory and is expensive to copy. ------------------------------------------------------------------------------------------------------- What is an Object
Object Oriented Programming is a programming style that is intended to make thinking about programming closer to thinking about the real world. In programming, objects are independent units, and each has its own identity, just as objects in the real world do. An apple is an object; so is a mug. Each has its unique identity. It's possible to have two mugs that look identical, but they are still separate, unique objects. ------------------------------------------------------------------------------------------------------ Objects
An object might contain other objects but they're still different objects. Objects also have characteristics that are used to describe them. For example, a car can be red or blue, a mug can be full or empty, and so on. These characteristics are also called attributes. An attribute describes the current state of an object. Objects can have multiple attributes (the mug can be empty, red and large). An object's state is independent of its type; a cup might be full of water, another might be empty. -------------------------------------------------------------------------------------------------------- Objects
In the real world, each object behaves in its own way. The car moves, the phone rings, and so on. The same applies to objects - behavior is specific to the object's type. So, the following three dimensions describe any object in object oriented programming: identity, attributes, behavior. ------------------------------------------------------------------------------------------------------ Objects
In programming, an object is self-contained, with its own identity. It is separate from other objects. Each object has its own attributes, which describe its current state. Each exhibits its own behavior, which demonstrates what they can do. In computing, objects aren't always representative of physical items. For example, a programming object can represent a date, a time, a bank account. A bank account is not tangible; you can't see it or touch it, but it's still a well-defined object - it has its own identity, attributes, and behavior. Dive right into Object Oriented Programming (OOP) with C++! -------------------------------------------------------------------------------------------------------- What is a Class
Objects are created using classes, which are actually the focal point of OOP.
The class describes what the object will be, but is separate from the object itself. In other words, a class can be described as an object's blueprint, description, or definition. You can use the same class as a blueprint for creating multiple different objects. For example, in preparation to creating a new building, the architect creates a blueprint, which is used as a basis for actually building the structure. That same blueprint can be used to create multiple buildings. Programming works in the same fashion. We first define a class, which becomes the blueprint for creating objects. Each class has a name, and describes attributes and behavior. In programming, the term type is used to refer to a class name: We're creating an object of a particular type. Attributes are also referred to as properties or data. ---------------------------------------------------------------------------------------------------------- Methods
Method is another term for a class' behavior. A method is basically a function that belongs to a class. Methods are similar to functions - they are blocks of code that are called, and they can also perform actions and return values. ----------------------------------------------------------------------------------------------------------- A Class Example
For example, if we are creating a banking program, we can give our class the following characteristics: name: BankAccount attributes: accountNumber, balance, dateOpened behavior: open(), close(), deposit()
The class specifies that each object should have the defined attributes and behavior. However, it doesn't specify what the actual data is; it only provides a definition. Once we've written the class, we can move on to create objects that are based on that class. Each object is called an instance of a class. The process of creating objects is called instantiation. Each object has its own identity, data, and behavior. ------------------------------------------------------------------------------------------------------------ Declaring a Class
Begin your class definition with the keyword class. Follow the keyword with the class name and the class body, enclosed in a set of curly braces. The following code declares a class called BankAccount:
class BankAccount { };
A class definition must be followed by a semicolon. ------------------------------------------------------------------------------------------------------------- Declaring a Class
Define all attributes and behavior (or members) in the body of the class, within curly braces. You can also define an access specifier for members of the class. A member that has been defined using the public keyword can be accessed from outside the class, as long as it's anywhere within the scope of the class object. You can also designate a class' members as private or protected. This will be discussed in greater detail later in the course. -------------------------------------------------------------------------------------------------------------- Creating a Class
Let's create a class with one public method, and have it print out "Hi".
class BankAccount { public: void sayHi() { cout << "Hi" << endl; } };
The next step is to instantiate an object of our BankAccount class, in the same way we define variables of a type, the difference being that our object's type will be BankAccount.
int main() { BankAccount test; test.sayHi(); }
Our object named test has all the members of the class defined. Notice the dot separator (.) that is used to access and call the method of the object. We must declare a class before using it, as we do with functions. -------------------------------------------------------------------------------------------------------------- Type in the missing parts to declare a class MyClass, with one public function named someFunction, which prints "hi from MyClass" to the screen.
class MyClass { public: void someFunction() { cout << "hi from MyClass" << endl; } }; -------------------------------------------------------------------------------------------------------------- Abstraction
Data abstraction is the concept of providing only essential information to the outside world. It's a process of representing essential features without including implementation details. A good real-world example is a book: When you hear the term book, you don't know the exact specifics, i.e.: the page count, the color, the size, but you understand the idea of a book - the abstraction of the book. The concept of abstraction is that we focus on essential qualities, rather than the specific characteristics of one particular example. --------------------------------------------------------------------------------------------------------------- Abstraction
Abstraction means, that we can have an idea or a concept that is completely separate from any specific instance. It is one of the fundamental building blocks of object oriented programming. For example, when you use cout, you're actually using the cout object of the class ostream. This streams data to result in standard output.
cout << "Hello!" << endl;
In this example, there is no need to understand how cout will display the text on the user's screen. The only thing you need to know to be able to use it is the public interface. ---------------------------------------------------------------------------------------------------------------- Abstraction
Abstraction allows us to write a single bank account class, and then create different objects based on the class, for individual bank accounts, rather than creating a separate class for each bank account. Abstraction acts as a foundation for the other object orientation fundamentals, such as inheritance and polymorphism. These will be discussed later in the course. ----------------------------------------------------------------------------------------------------------------- Encapsulation
Part of the meaning of the word encapsulation is the idea of "surrounding" an entity, not just to keep what's inside together, but also to protect it. In object orientation, encapsulation means more than simply combining attributes and behavior together within a class; it also means restricting access to the inner workings of that class.
The key principle here is that an object only reveals what the other application components require to effectively run the application. All else is kept out of view. This is called data hiding. ------------------------------------------------------------------------------------------------------------------ Encapsulation
For example, if we take our BankAccount class, we do not want some other part of our program to reach in and change the balance of any object, without going through the deposit() or withdraw() behaviors. We should hide that attribute, control access to it, so it is accessible only by the object itself. This way, the balance cannot be directly changed from outside of the object and is accessible only using its methods. This is also known as "black boxing", which refers to closing the inner working zones of the object, except of the pieces that we want to make public. This allows us to change attributes and implementation of methods without altering the overall program. For example, we can come back later and change the data type of the balance attribute.
In summary the benefits of encapsulation are: - Control the way data is accessed or modified. - Code is more flexible and easy to change with new requirements. - Change one part of code without affecting other part of code. ------------------------------------------------------------------------------------------------------------------- Access Specifiers
Access specifiers are used to set access levels to particular members of the class. The three levels of access specifiers are public, protected, and private. A public member is accessible from outside the class, and anywhere within the scope of the class object. For example:
#include <iostream> #include <string> using namespace std; class myClass { public: string name; }; int main() { myClass myObj; myObj.name = "Art2Dec"; cout << myObj.name; return 0; }
//Outputs "Art2Dec"
The name attribute is public; it can be accessed and modified from outside the code. Access modifiers only need to be declared once; multiple members can follow a single access modifier. Notice the colon (:) that follows the public keyword. -------------------------------------------------------------------------------------------------------------------- Private
A private member cannot be accessed, or even viewed, from outside the class; it can be accessed only from within the class. A public member function may be used to access the private members. For example:
#include <iostream> #include <string> using namespace std; class myClass { public: void setName(string x) { name = x; } private: string name; }; int main() { myClass myObj; myObj.setName("John"); return 0; }
The name attribute is private and not accessible from the outside. The public setName() method is used to set the name attribute. If no access specifier is defined, all members of a class are set to private by default. -------------------------------------------------------------------------------------------------------------------- Access Specifiers
We can add another public method in order to get the value of the attribute.
class myClass { public: void setName(string x) { name = x; } string getName() { return name; } private: string name; };
The getName() method returns the value of the private name attribute. --------------------------------------------------------------------------------------------------------------------- Access Specifiers
Putting it all together:
#include <iostream> #include <string> using namespace std; class myClass { public: void setName(string x) { name = x; } string getName() { return name; } private: string name; }; int main() { myClass myObj; myObj.setName("John"); cout << myObj.getName(); return 0; }
//Outputs "John"
We used encapsulation to hide the name attribute from the outside code. Then we provided access to it using public methods. Our class data can be read and modified only through those methods. This allows for changes to the implementation of the methods and attributes, without affecting the outside code. --------------------------------------------------------------------------------------------------------------- Type in the missing parts to declare a MyClass object, and set its data member's value to 14, then print its value to the screen. Do all mentioned operations via the public functions setMyData and getMyData.
int main() { MyClass obj; obj.setMyData(14); cout << obj.getMyData() << endl; } -------------------------------------------------------------------------------------------- Constructors
Class constructors are special member functions of a class. They are executed whenever new objects are created within that class. The constructor's name is identical to that of the class. It has no return type, not even void. For example:
class myClass { public: myClass() { cout <<"Hey"; } void setName(string x) { name = x; } string getName() { return name; } private: string name; }; int main() { myClass myObj; return 0; }
//Outputs "Hey"
Now, upon the creation of an object of type myClass, the constructor is automatically called. ------------------------------------------------------------------------------------------------- Constructors
Constructors can be very useful for setting initial values for certain member variables. A default constructor has no parameters. However, when needed, parameters can be added to a constructor. This makes it possible to assign an initial value to an object when it's created, as shown in the following example:
class myClass { public: myClass(string nm) { setName(nm); } void setName(string x) { name = x; } string getName() { return name; } private: string name; };
We defined a constructor, that takes one parameter and assigns it to the name attribute using the setName() method. ----------------------------------------------------------------------------------------------------- Constructors
When creating an object, you now need to pass the constructor's parameter, as you would when calling a function:
class myClass { public: myClass(string nm) { setName(nm); } void setName(string x) { name = x; } string getName() { return name; } private: string name; }; int main() { myClass ob1("David"); myClass ob2("Amy"); cout << ob1.getName(); } //Outputs "David"
We've defined two objects, and used the constructor to pass the initial value for the name attribute for each object. It's possible to have multiple constructors that take different numbers of parameters. --------------------------------------------------------------------------------------------------------
|