Nuts and Bolts of C++

Compiler -> Linker + Library -> Executable Machine Language Program

Library belongs to the operation system.

High-level Languages (HLL)

Recent Examples

  • Pascal

  • C

Current Examples

  • C++

  • Java

C++ program is portable to different machines.

Visual Studio

A Solution must contain at least one project.

A Project must contain at least one file.

In Visual Studio, each user task is referred to as a solution to a problem.

In Visual Studio, every project mainly contains:

  • Executable code and debug information
  • C++ source code
  • Classes and objects

Command Prompt

Command Prompt – a traditional interface between the user and computer

some basic command:

cd – change directory

dir – directory

cin and cout

cin is the keyboard. cout is the display.

cin.get() only gets the first character.

enter also count as a character.

Preprocessor

#include <iostream>

  • Instruct the compiler on how to complie the program
  • Will not generate machine codes
  • Start with a pound (#) symbol

Header Files

  • Definitions of some terms in the program codes are recorded in some header files
  • Can be shipped with the compiler or other resources
  • #include tells the compiler where to find the header file and insert this file to that location of the program
    • #include <iostream> tells the compiler it should get the file iostream through the default path
    • #include "myfile" tells the comiler it should get the file myfile in the current path

Actual program (main function)

  • Every C++ program must have the main() function
  • It is the beginning point of every C++ program

Program codes

  • The basic element of a program is a function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
int main() // Return Type | Function name | (Input parameters)
{
std::cout << "Hello World!" << std::endl; //send the string
//In C++, a string is represented by a sequence of characters enclosed by " "
return 0; // send some data back to the operation system
}// Program codes enclosed by the opening and closing braces

//-------------Another example

#include <iostream>
using namespace std; //Use this to save typing effort
int main()
{
cout << "Hello World!" << endl; //no need std:: anymore
return 0;
}

Namespaces

  • std::cout and std::endl means that we are referring to the cout and endl of the std namespace
  • Design to help programmers develop new software components without generating naming conflicts

Naming Conflict

  • cout and endl are NOT C++ keywords, people can use these two names for any purpose.
  • not necessarily referring to the standard output and newline character.
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
namespace myns{
int cout=0; //integer variable
} //No semi-colon needed

int main(){
std::cout << myns::cout << std::endl; //std::cout refer to standard output
return 0;
}

//result of this program is a number 0 shown on the standard output.

Common useful things

Character What it means
\n new line
\t Tab
\b Backspace
\" double quote
\' Single quote
\\ Backslash

Comments

  • Improve readability

  • Will not affect the program

    1
    2
    //This is a comment.
    /*This is a multline comment. */

Functions

it is a bad habit to do everything by a single function.

  • When the function returns, the program goes back to where it left before.
  • The function main() can call other functions to help completing a task.

Note: If you want to write a function and put it under main, you need function prototype.

Example1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
//function DemonstrationFunction()
// show a useful message
void DemonstrationFunction(){ //void means return nothing
cout << "In Demonstration Function\n";
cout << "Print one more line\n";
}
//function main - prints out a message, then
//calls DemonstrationFunction(), then shows the second message.
int main()
{
cout << "In main\n";
DemonstrationFunction();
cout << "Back in main\n";
return 0;
}

//result:
//In main
//In Demonstration Function
//Print one more line
//Back in main

Example2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
int Add (int x, int y) //Input parameters need to declare type.
{
cout << "In Add(),received "<<x<<" and "<<y<<"\n";
return(x+y); //returns an integer x+y back to main()
}
int main()
{
cout << "I'm in main()!\n";
int a,b,c;
cout << "Enter two numbers: ";
cin >> a;
cin >> b;
cout << "\nCalling Add()\n";
c = Add(a,b); //Add() is called with two parameters and c holds the return value of Add()
cout << "\nBack in main().\n";
cout << "c was set to " << c;
cout << "\nExiting...\n\n";
return 0;
}

Variables and Memory

  • A variable is associated with a place (Location in the memory) to store information in a computer
  • The name of a variable can be considered as a label of that piece of memory
  • Computer change the content of memory when the program modify the value of variable
  • Every data is reflected with type and value.
  • One adress for one byte, i.e. 8 bits of memory.

Types of Variables

Type Size Values
bool 1 byte 1 or 0
unsigned short int 2 bytes 0 to 65,535
short int 2 bytes -32,768 to 32,767
unsigned long int 4 bytes 0 to 2^32-1
long int 4 bytes -2147483648 to 2147483647
unsigned int 4 bytes 0 to 2^32-1
int 4 bytes -2147483648 to 2147483647
char 1 byte 256 character values
float 4 bytes (+/-) 1.2e-38 to (+/-)3.4e38
double 8 bytes (+/-) 2.2e-308 to (+/-) 1.8e308

What so special about 2147483648?

Declaring Variable

  • When we use a variable, we need to declare its type so that the computer can reserve suitable memory space for it.

  • Programmer do not need to know the adress.

  • The name of the variable is case sensitive. (int myVariable is not the same as int myvariable)

  • Declared uninitialized variable have a default value.

Maximum and Minimum

When the value goes beyond those limits, unexpected behavior may result.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
int main()
{
unsigned short int smallNumber;
smallNumber = 65535; // 1111 1111 1111 1111 = 65535
cout << "small number:" << smallNumber << endl;
smallNumber++; //1 0000 0000 0000 0000 = 0
cout << "small number:" << smallNumber << endl;
smallNumber++; // 0000 0000 0000 0001 = 1
cout << "small number:" << smallNumber << endl;
return 0;
}

//result
// small number: 65535
// small number: 0
// small number: 1

Signed integers do NOT behave in the same way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
int main()
{
short int smallNumber;
smallNumber = 32767; // 0111 1111 1111 1111 = 32767
cout << "small number:" << smallNumber << endl;
smallNumber++; // 1000 0000 0000 0000 = -32768
cout << "small number:" << smallNumber << endl;
smallNumber++; // 1000 0000 0000 0001 = -32767
cout << "small number:" << smallNumber << endl;
return 0;
}

//result
// small number: 32767
// small number: -32768
// small number: -32767

Characters

  • Char

    1
    2
    3
    4
    5
    char c = 53, d = '5'; //They are the same
    // c = 5, d = 5

    char character = a;
    character = a + 1; // a now become 'b' (refer to ascii table!!)
    • only consider the variable as an 8-bit ASCII character. ascii table
    • ‘’ is for single character

Constants

The value of a constant will be fixed until the end of the program.

  • Literal Constants - come with the language
  • Symbolic Constants - we define a special name as a label to it

Defining Symbolic Constants (2 ways)

  1. Old way (#define is the command from preprocessor)
1
2
3
#define student 87
// No type needs to be defined
// The preprocessor just replaces the word "student" with 87 wherther it is found in the source program.
  1. Better way (keyword - const)
1
2
3
const unsigned short int student = 87;
// The data student now has a fixed value 87
// it has a type, this feature helps the compiler to debug the program.

Usage of Constants

  • Help debugging the program - compiler automatically check if a constant is modified by the program
  • Improve readability - give the value a meaningful name
  • Easy modification - only need to change single line in the source program

If Statement

1
2
3
4
if(condition) //remember the () follow the if
{
//do something when condition is true.
}

sometimes you dont need {}. Only the statement follows the if statement will check the condition.

1
2
3
if(condition)
cout << "Hi";
cout << "This message doesnt check the condition";

Enumerated Constants

Look at this for more info.

Allow one to create a new type that contains a number of constants

If the following item is not declared a value, it will be the previous value + 1.

The first value will be 0.

1
2
3
enum COLOR {RED, BLUE, GREEN, WHITE, BLACK};
// Makes COLOR the name of the new type
// RED = 0, BLUE = 1, GREEN = 2, WHITE = 3, BLACK = 4.
1
2
3
enum COLOR2 {RED = 100, BLUE, GREEN = 500, WHITE, BLACK = 700};
// Makes COLOR2 the name of the new type
// RED = 100, BLUE = 101, GREEN = 500, WHITE = 501, BLACK = 700.

When to use it?

Look at this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
int main()
{
const int Saturday = 6;
const int Friday = 5;
const int Thursday = 4;
const int Wednesday = 3;
const int Tuesday = 2;
const int Monday = 1;
const int Sunday = 0;

int choice;
cout << "Enter a day (0-6): ";
cin >> choice;
if ((choice == Sunday) || (choice == Saturday))
cout << "\nIt's a holiday!\n";
else //Otherwise
cout << "\nIt's not a holiday yet.\n";
return 0;
}

// == means check the condition
// || is logical OR.

After using enumerated constants:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
int main()
{
enum Days {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
int choice;
cout << "Enter a day (0-6): ";
cin >> choice;
if ((choice == Sunday) || (choice == Saturday))
cout << "\nIt's a holiday!\n";
else //Otherwise
cout << "\nIt's not a holiday yet.\n";
return 0;
}

// == means check the condition
// || is logical OR.

A Typical Program

Statements

1
x = a + b; //an simple statement
  • A C++ program comprises a number of functions

  • A function comprises a number of statements

    A statement must end with a semicolon ;

    spaces in statement nearly carry no information.

Expressions

1
2
3
3.2; //returns the value 3.2
x = a + b; //Here, Two expressions
// Returns a+b, returns the value of x
  • An expression reutrns a value.

Operators

  • An expression often comprises one of more operators

  • Assignment operator ‘=’ assigns a value to a variable

    Operators Meaning
    + Add
    - Subtract
    * Multiply
    / Divide
    % Modulus
1
2
3
4
5
6
7
int a = 3, b = 4, x;

x = a+b; //x=7
x = a-b; //x=-1
x = a*b; //x=12
x = a/b; //x=0 (why?)
x = a%b; //x=3 (why?)

Integer and Floating Point Divisons

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
// NOTE : x,y of main() are NOT the x,y of intDiv()!!!!!
void intDiv(int x, int y)
{
int z = x/y;
cout << "z: " << z << endl;
}
void floatDiv(int x, int y)
{
//Line 11 and 12 Ask compiler to temporarily consider x as a floating point number.
float a = (float)x; // old style
float b = static_cast<float>(y); // ANSI style <-- new style which I dont like it

float c = a/b;
cout << "c: " << c << endl;
}
int main()
{
int x = 5, y = 3;
intDiv(x,y); //Only give integer division result
floatDiv(x,y); //Give floating point division result
return 0;
}

//result:
//z: 1
//c: 1.66667

Short Hand of Expressions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Add
c = c + 1;
c += 1;
c++; //note it is only for +1
++c; //note it is only for +1

//Minus
c = c - 1;
c -= 1;
c--; //note it is only for -1
--c; //note it is only for -1

//Multi
c = c * 4;
c *= 4;

//Div
c = c/ 5;
c /= 5;

++ variable vs variable ++

1
2
3
int c = 5;
a = c++; // a = 5, c = 6 as a = c first and then c++

1
2
int c = 5;
a = ++c; // a = 6, c = 6 as ++c first and then a = c

Precedence and Parentheses

  • Performed from left to right
  • first multi/div then add/subtract
  • Parentheses can be nested as in normal arithmetic

Relational Operators

Operators Meaning
== Equals
!= Not Equals
> Greater than
>= Greater than or equals
< Less than
<= Less than or equals

Logical Operators

  • Logical operators evaluate expressions of bool values

  • Each logical operation returns a bool result (true or false)

Operators Meaning Examples
&& AND condition1 && condition2
|| OR condition1 || condition2
! NOT !condition1

Program Flow Control

Control of Program Flow

  • if… else
  • switch… case … break

An example of if statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
int main()
{
int x;
cout << "Enter a number x < 10 or x > 100: ";
cin >> x;
cout << "\n";
if (x >= 10) //{
if (x > 100)
cout << "More than 100, thanks!\n"; //}
else // not the else intended!
cout << "Less than 10, thanks!\n";
return 0;
}

//See what happens if braces are uncommented?

An example of Switch statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
int main()
{
unsigned short int num; //NOT for double and float
cout << "Enter a number between 1 and 5: ";
cin >> num;
switch (num) //Only accept number or expression that returns a number,
//NOT floating point no.
{ case 0: cout << "Too small, sorry!";
break; //Note the differences between break and no break
case 3: cout << "Excellent!\n"; //falls through
case 2: cout << "Masterful!\n"; //falls through
case 1: cout << "Incredible!\n";
break;
default: cout << "Too large!\n"; //Do default if all tests fail
break;
}
cout << "\n\n";
return 0;
}

//Result
//Enter a number between 1 and 5: 3
//Excellent!
//Masterful!
//Incredible!

Switch statement can be implemented by the If statement but with more complicated structure. However, Switch can only be applied to data value tests.

Looping

  • Many programming problems are solved by repeatedly acting on the same variables

  • The method for achieving repeated execution is by looping

C++ offers many approaches to realise looping

  • if … goto <-- Old way, abandoned by the public
  • while loop <-- Use when testing parameters are complicated
  • do-while loop <-- Use when the repeated part is expected to be executed at least once
  • for loop <-- Use when the testing parameters are simple

While loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int main()
{
int counter = 0; //initialize counter
while (counter<5) //Test Condition (tested variable must change inside the loop)
{
counter++; //update the variable value
cout << "counter: " << counter << "\n";
}
cout << "Complete. Counter: " << counter << ".\n";
return 0;
}

//Result:
//counter: 1
//counter: 2
//counter: 3
//counter: 4
//counter: 5
//Complete. Counter: 5.

while loops do the looping until the testing condition fails.

Do … While loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int main()
{ int counter;
cout << "How many hellos? ";
cin >> counter;
do
{ cout << "Hello\n"; //Hello will be shown at least once
//even if the user enters 0 for counter
counter--;
} while (counter > 0);
cout << "Counter is: " << counter << endl;
return 0;
}

//Results
//How many hellos? 0
//Hello
//Counter is: -1

while loops do the test first and then the loop.

Sometimes we would like to have the loop to be done at least once. In this case, do … while can be used

For loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
int main()
{
int counter;
for (counter=0; counter<5; counter++) //Initialization; Condition; Increment
cout << "Looping! "; //counter then increment
cout << "\nCounter: " << counter << ".\n";
return 0;
}

//Results:
// Looping! Looping! Looping! Looping! Looping!
// Counter: 5.

It can be done in a single line by a for loop. Tricky but convenient to use.

For loop also support Multiple/Null initialization and increments, or even empty for loop.

Multiple initialization and increments

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main()
{ for (int i=0, j=0; i<3; i++, j++) //Multiple initialization and increments
cout << "i: " << i << " j: " << j << endl;
return 0;
}

//Results:
//i: 0 j: 0
//i: 1 j: 1
//i: 2 j: 2

Null initialization and increments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
int main()
{ int counter = 0;
for (; counter < 5;) //Null initialization and increments
{ counter++;//BEFORE doing the looping task
cout<<"Looping! ";
}
cout << "\nCounter: " << counter << ".\n";
return 0;
}

//Results:
// Looping! Looping! Looping! Looping! Looping!
// Counter: 5.

Empty For Loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
int main()
{ int counter = 0; // initialization
int max;
cout << "How many hellos?";
cin >> max;
for (;;) // a for loop that doesn't end
{ if (counter < max) // test
{ cout << "Hello!\n";
counter++; // increment
}
else
break; //end for loop
}
return 0;
}

//Results:
// How many hellos? 3
// Hello!
// Hello!
// Hello!

Continue and break

The keywords continue and break change the program flow during looping

Use with caution as it makes the program hard to understand owing to the sudden change of direction

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
int main()
{ int counter;
for (counter=0; counter<5; counter++)
{ cout << "Looping! counter is " << counter <<"\n";
if ((counter%2) == 1) //odd number
continue; //Execution of continue will skip the following part of the loop
//but NOT leaving the loop
cout << "Counter is an even number.\n";
}
return 0;
}

Rewrite Looping program into other looping program

Look at this example. This is a nested for loops. Take time to get familiarise with it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
int main()
{
int rows, columns, i, j;
char theChar;
cout << "No. of rows? ";
cin >> rows;
cout << "No. of columns? ";
cin >> columns;
cout << "Which characters? ";
cin >> theChar;
for (i=0; i<rows; i++)
{
for (j=0; j<columns; j++)
cout << theChar;
cout << "\n";
}
return 0;
}

//Results:
//No. of rows? 2
//No. of columns? 3
//Which characters? a
//aaa
//aaa

Now I change it into nested do while loop. Do…while program also do the same but it is more complicated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
using namespace std;
int main()
{
int rows, columns, i, j;
char theChar;
cout << "No. of rows? ";
cin >> rows;
cout << "No. of columns? ";
cin >> columns;
cout << "Which characters? ";
cin >> theChar;


do{
do{
cout << theChar;
j++;
} while (j < columns);
cout << "\n";
i++;
j=0;
} while (i < rows);

return 0;
}


//Results:
//No. of rows? 2
//No. of columns? 3
//Which characters? a
//aaa
//aaa

Functions

Why do we need functions?

  • Functions help us shorten our program by re-using the program codes.
  • The same program will be much longer without calling functions
  • Can be even longer if the same operation is done in other parts of the program.
  • Functions make our program much easier to read

Declaring Functions

Function Prototype

unsigned short int FindArea(int, int);

Return type – function name – type of input parameters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int Area(int length, int width); // function prototype
int main()
{
int lengthOfYard;
int widthOfYard;
int areaOfYard;
cout << "\nHow wide is your yard? ";
cin >> widthOfYard;
cout << "\nHow long is your yard? ";
cin >> lengthOfYard;
areaOfYard = Area(lengthOfYard,widthOfYard);
cout << "\nYour yard is ";
cout << areaOfYard;
cout << " square feet \n\n";
return 0;
}
int Area(int yardLength, int yardWidth)
{
return yardLength * yardWidth;
}

Function Prototypes in Header file

Advantage: if a particular set of function prototypes is often used in different programs, we need not declare them line by line every time they are needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//sourceFile.cpp
#include <iostream>
#include "myHeader.h";
using namespace std;

void floatDiv(int x, int y)
{
float a = (float)x;
float b = static_cast<float>(y);
float c = a/b;
cout << "c: " << c << endl;
}
int main()
{
int w = 8, x = 6, y = 4, z = 3;
floatDiv(w,x);
floatDiv(x,y);
floatDiv(y,z);
return 0;
}

Add a header.

1
2
//myHeader.h
void floatDiv(int x, int y);

Variables of Functions

there are 3 types of variables that a function may make use of:

Passed parameters and return parameter

  • The links between the called function and the calling function

Local variable

  • Visible only within a function, For temporary local storage
  • A function can define local variables for temporary use.
  • Local variables are only visible within the function defining them
  • If both main() used the same name of global variable and local variable, Local variable has a higher priority.

Global variable

Global variable

  • Visible to ALL functions in the program, An old and dangerous way to communicate between functions
  • Must be carefully used
  • Make your program difficult to debug

Variable Stored in Data Memory.

Paramater Passing - Passed by Value

  • only a copy of the parameter value is passed to the called function
  • what the called function does to the passed parameters has nothing to do with the original one, since they are just two variables (and occupying different memory, even when their names are the same)

Scope of Variables

Variables declared within a pair of braces are visible only to the statements in that braces after the variable is declared.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
void myFunc()
{
int x = 8;
cout << "\nIn myFunc, local x: " << x << endl; //x=8
{
cout << "\nIn block in myFunc, x is: " << x; //x=8
int x = 9; //This x is not the same as the previous x
cout << "\nVery local x: " << x; //x=9
}
cout << "\nOut of block, in myFunc, x: " << x << endl; //x=8
}
int main()
{
myFunc();
return 0;
}

Default Parameters

  • Calling function should pass the same number of parameter values as those defined in the prototype of the called function
1
long myFunction(int); //function prototype
  • One exception is if the function prototype’s parameter has a default value
1
long myFunction(int x = 50); //default value

If the calling function does not provide a parameter value, 50 will be automatically used.

Look at this example.

Once a default value is given, the parameters that follow must have default values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
int volumeCube(int, int width = 25, int height = 1); //May use other names, or even no name
int main()
{
int length = 100, width = 50, height = 2, volume;
volume = volumeCube(length, width, height);
cout << "First volume equals: " << volume << "\n"; //volume = 100×50×2= 10000
volume = volumeCube(length, width);
cout << "Second volume equals: " << volume << "\n"; //volume = 100×50×1 = 5000
volume = volumeCube(length);
cout << "Third volume equals: " << volume << "\n"; //volume = 100×25×1 = 2500
return 0;
}
int volumeCube(int length, int width, int height)
{
return (length*width*height);
}

Overloading Functions

C++ allows overloading of function, i.e. create more than one function with the same name

1
2
3
4
5
int myFunction (int, int);
int myFunction (long, long);
long myFunction (long);
//3 different functions
//Differ by just the return type is NOT allowed

When a function calls myFunction(), the compiler checks the number and type of the passed parameters to determine which function should be called.

Look at this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;
int intDouble(int);
float floatDouble(float);
int main()
{
int myInt = 6500, doubledInt;
float myFloat = 0.65, doubledFloat;
doubledInt = intDouble(myInt);
doubledFloat = floatDouble(myFloat);
cout << "doubledInt: " << doubledInt << "\n";
cout << " doubledFloat : " << doubledFloat << "\n";
return 0;
}
int intDouble(int original)
{
return 2*original;
}
float floatDouble(float original)
{
return 2*original;
}
//The objective of both functions is to double the passed parameter
//It looks much better to have a single function name but different parameter types
//Overloading allows us to do so

Overloading example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int Double(int);
float Double(float);
int main()
{
int myInt = 6500, doubledInt;
float myFloat = 0.65, doubledFloat;
doubledInt = Double(myInt);
doubledFloat = Double(myFloat);
cout << "doubledInt: " << doubledInt << "\n";
cout << " doubledFloat : " << doubledFloat << "\n";
return 0;
}
int Double(int original) //Overloading
{
return 2*original;
}
float Double(float original) //Overloading
{
return 2*original;
}

Writing a Good Program

Debugging a big program is exponentially more difficult than a small program.

  • If a big program is to be developed, always try to break it down to many small programs (functions) and debug them independently. Divide and Conquer.
  • Usually main() is only used to indicate the program flow. The actual task is done by the functions called by main(). By looking at the sequence of functions called by main(), people basically understand what is going on in a program.
  • main() gives the skeleton of a program.

Improve the Readability of Programs

In practice, the time a programmer spends in documentation is more than writing the program.

  • A program is seldom developed by a single person, cooperations are needed between programmers or even teams of programmers
  • Besides, a program developed by a team of programmers often needs to be maintained by another team

It is essential that a program is properly documented to help team work.

Documenting a Program - readme (for user)

I Personally recommend markdown file (readme.md).

Not only it is often used it github, it is also very convinent to use.

I recommend using Typora to edit markdown files.

After developing a program, a readme file is often prepared in practice to indicate the following:

  • Background information of the program (e.g. objectives, version no., development date, developer name)
  • How to use the program (e.g. command line options)
  • Additional resource required (e.g. hardware, driver, etc.)
  • Bugs fixed as compared to previous version(s)
  • Possible conflict with other programs

Within a program - comments (for developer)

  • Commenting a program is the responsibility of every programmer
  • Need meaningful comments (explain something people will have difficulty to understand)

Developing a program step-by-step

Step 0 – Prepare a flowchart

  • To better visualize the problem, we may develop a flowchart for it

Step 1 – construct the skeleton

  • What will be in the main function?

Step 2 – Add stubs (i.e. just for testing)

  • stubs is a function that assure the program can successfully build
  • We need to ensure the skeleton is correct before we proceed to implement the functions – add stubs

Step 3 – Implement functions

  • If the skeleton has been proved to be correct, start to implement functions
  • It is desirable to further break a big function into smaller functions

Step 4 – Implement the sub-functions

  • It is desirable to have each function contained at most 20 lines of codes.

Debugging a Program

It is often NOT the case that a program can run correctly once it is developed.

Therefore, Debugging is often a necessary procedure.

Debugging can be divided into the following two stages:

Compile-time debugging (relatively easy)

  • Compile-time errors can often be spotted out by the compiler
  • The compiler can detect the approximate error location, but cannot be exact
  • Also, the error messages generated are sometimes irrelevant
  • Correct the errors owing to incorrect use of language syntax or unresolved references
  • When a series of error messages are found, always try to debug them starting from the first one
  • Once the first one is corrected, the rest may be solved as well.

Run-time debugging (often far more difficult)

  • Comparing with compile-time errors, runtime errors are more difficult to locate and correct
  • Run-time errors are often caused by wrong programming logic or improper use of resources
  • Run-time errors may sometimes lead to incorrect results or even system failure
  • Even worst, some run-time errors give no observable problem but gradually damage the system or the database.
  • Correct the errors owing to incorrect program logic or resource usage

How to Avoid Run-time Errors?

C++ has many standard features to allow possible run-time errors be detected during compile-time

Try your very best to enable the compiler to detect the errors for you (that is, to convert run-time errors to compile-time errors whenever possible).

A structured way in program development can help avoid run-time errors.

Never develop your program in one step. Always ensure the skeleton is correct before going forward.

How to Debug Run-time Errors?

The problem of run-time errors can be observed only at run-time. One has to run the program in order to debug run-time errors

To debug run-time errors, the first thing that has to be done is to locate the errors

Achieved by the divide and conquer approach: The simplest way is to set some check-points in the program and to see how many checkpoints the program can correctly get through.

Run-time Debugger of Visual Studio

In some IDEs, there is a debug mode that allows you to set a breakpoint and check the variables.

To help in debugging more complicated run-time errors, Visual Studio has provided a run-time debugger:

  • Allow line-by-line tracing of program code
  • Allow arbitrary breakpoint in a program
  • Allow examination of the status of all resources at the breakpoints, such as what data present in memory, data value of variables
  • Allow monitoring of a particular resource of interest
Button Usage
Breakpoint A line number of interest in your program. When the debugger is running it halts execution of the program at this line.
Call stack A list of functions in the debugger that explains how the program got to where it currently is. Think of this as a live stack trace, without the exception.
Continue  An action to take in the debugger that will continue execution until the next breakpoint is reached or the program exits.
Step over An action to take in the debugger that will step over a given line. If the line contains a function the function will be executed and the result returned without debugging each line.
Step into An action to take in the debugger. If the line does not contain a function it behaves the same as “step over” but if it does the debugger will enter the called function and continue line-by-line debugging there.
Step out An action to take in the debugger that returns to the line where the current function was called.

Basically:

  1. Click on the lines of code where you would like to set

Right-click → Breakpoint → Insert Breakpoint

  1. Build it successfully. Start the debugger by clicking Debug → Start Debugging

Look at the Status window: Give the value of all related variables. Can also particularly watch the result of an expression by typing it in.

  • Step Into: Like Step Over, but if the current statement is a function calling, go into the called function to debug

  • Step Out: Return to the calling function

  • Step Over: Execute just the current line

Check View → Toolbars → Debug if you cannot see the debug toolbar.

  1. Step over the code

On stepping over each line of code, the current values of the variables are shown

  1. Find the error and stop Debugging. Go back to the source and fix the error.

Basic Object Oriented Programming

What is an Object?

An Object has it own states and behaviors.

When come to software, Software designers use the same idea to ease programmers to develop their software.

Each Software object also has its own states and behaviors.

methods (behavior) and attributes (states)

Encapsulation (Data Hiding)

  • Hiding Information
  • Provide a public interface for interacting with it

Advantages to software developers

  • Modularity: An object can be easily passed around in the system. (Library, Reusability)
  • Information hiding: Users need not go into details of the object before using the object.
  • Safety: Users of the object may not directly access the internal state of the object. Reduce Errors.

What is a Class?

A Class is a blueprint of prototype that defines the variables and methods (functions) common to all objects of a certain kind. Every object of a class is an instance of that class.

Benefit - Reusability. Save effort in developing a number of objects of the same kind.

Declaring Classes in C++

To declare a class, use the class keyword.

1
2
3
4
5
6
class Cat
{
unsigned int itsAge; // Member variable
unsigned int itsWeight;// Member variable
void Meow(); // Member function
}; //Remember this semicolon!!!
  • Declaring the class does not allocate any memory for a Cat
  • Only tell the compiler what a Cat is, the attributes and functions of the cat.
  • Declaration of classes should be placed in the header file and included into your program. #include

Declaring an Object of a Class

When a class is defined, we can further declare the objects of that class:

1
2
Cat Frisky; // declare 1 Cat object called Frisky
//It states that we are going to handle a Cat called Frisky

Obviously, one can declare two cats as follows:

1
2
3
Cat Frisky, Felix; // declare 2 Cat objects
// Note that Frisky is never the same as Felix,
//although they both belong to the class Cat, i.e. they are Cat objects.

Accessing Class Members

When an object is defined, we can access the members of that object based on its class definition.

The operator ‘.’ allows us to access the members of the object.

1
2
unsigned int weight = Frisky.itsWeight;
// Get the weight of Frisky

Never access directly to class.

1
//Cat.itsAge = 5; // Don’t do that! Cat is class

Private vs Public

Members can be divided into public members or private members.

  • Private members of a class are those members that can only be accessed by member functions of that class. By default, all members are private.
  • Public members of a class are those members that can be accessed by other functions and class objects.

This mechanism provides the privacy or security to the information of a class that requires protection.Typically, access private members by public methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream> // for cout
using namespace std;
class Cat // declare the class
{
public: // If it is private, An error is generated since They cannot be accessed by main().
int itsAge;
int itsWeight;
};

int main()
{
Cat Frisky;
Frisky.itsAge = 5; // assign to the member variable
cout << "Frisky is a cat who is ";
cout << Frisky.itsAge << " years old.\n";
return 0;
}

How Private Variables Are Used?

Use Getters and Setters.

Set is for writing while Get is for reading.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream> // for cout
using namespace std;
class Cat // declare the class Cat
{
public:
//Public Accessor Methods:
void SetAge (int age);
int GetAge();
void SetWeight (int weight);
int GetWeight();
private:
// Private member variables
int itsAge;
int itsWeight;
};

//Accessor methods provide access to private members since they are in the same class.
int Cat::GetAge() //To indicate GetAge() is a function of the class Cat
{
return itsAge;
}
void Cat::SetAge(int age)
{
itsAge = age;
}

int Cat::GetWeight()
{
return itsWeight;
}
void Cat::SetWeight(int weight)
{
itsWeight = weight;
}

Note: People can only read your class info while only you knows whats inside the function.

Private vs Public vs Protected

More info about protected

Constructors and Destructors

We can initialize an object using constructors.

  • Every class should have a constructor
  • User can define its own constructor for the class
  • Otherwise, the compiler will make one for the user although it does nothing

Constructor is a function of which the program will call if an object of this class is constructed (created) and stored in memory. Besides constructor, every class has also a destructor that will be called when the object of that class is destructed (removed).Data memory released

Note: No return type needed for constuctors and destructors.

Look at this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class Cat
{
//A typical Class definition with userdefined constructor and destructor
public:
Cat(int initialAge); // Constructor of Cat
~Cat(); // Destructor of Cat
// Note: No return type needed for constuctors and destructors!
int GetAge();
void SetAge(int Age);
void Meow(); //public function
private:
int itsAge;
};

Cat::Cat(int initialAge)
{
/*
Implementation of constructor: When any
object of the class Cat is constructed,
this function is called and in effect it
will set itsAge to the parameter passed.
*/
itsAge = initialAge;
}
Cat::~Cat()
{
/*
Implementation of destructor: When
any object of the class Cat is
destructed, this function is called
which does nothing here.
*/
}
void Cat::Meow() {}

int Cat::GetAge() //To indicate GetAge() is a function of the class Cat
{
return itsAge;
}
void Cat::SetAge(int age)
{
itsAge = age;
}

//A possible main() function for the class Cat can be :
#include <iostream>
using namespace std;
int main()
{
/*
A Cat Frisky is constructed here.
The constructor is called and the
parameter 5 is passed to the
constructor and in turn initializes the
private member variable itsAge to 5
*/
Cat Frisky(5);
Frisky.Meow();
cout << "Frisky is a cat who is ";
cout << Frisky.GetAge() << " years old.\n";
Frisky.Meow(); //Meow() does nothing here
Frisky.SetAge(7);
cout << "Now Frisky is ";
cout << Frisky.GetAge() << " years old.\n";
Frisky.Meow();
return 0;
}

const Member Functions

It is possible that some functions will never change the value of any member variable.

  • It is desirable to declare them as const member function
  • Then, the compiler will automatically check if there is any inconsistency in the program
  • It helps to debug the program
1
2
3
int GetAge() const; // add the keyword const when
int GetWeight() const; // you declare the functions
// Use const when you want to function to be read only!

So What will a class contain?