Nuts and Bolts of C++ [2]
Modular Programming with C++
Doing Business by Selling Classes
The development of Object Oriented Programming has enabled a new business in software development.
- Develop different classes and sell to other people
These classes often provide functions that are popularly used in applications
- E.g. the Java calculator used in some Web pages
Assume that you have designed some class and would like to sell it to a customer.
- You do not want to give him the source code of the member functions since your customer may copy your code
- They may modify it and re-sell it to somebody else
Therefore, It is better to give your customer executable code such that they cannot read or modify it.
Static Library
- Rather than giving your customer the executable code, you can give him a (static) library
- Inside a library, it does not contain the executable code, but the object code – machine code waiting for linking
- Since object code can not be read directly (not readable by human), your customer cannot modify your codes
- To enable your customer know how to use your class, give also your customer a header file that contains the definition of your class.
To Sell the library, only give the header file and the library. (Dont give out your source code!)
Create a Static Library with Visual C++
- Create the class required
- Implement the class
- Test the class
- Create the library with Visual C++
- Send the library and header file to the System Analyst
- Integrating into the Application
Modular Program Design
Besides doing business with classes, the use of static library also facilitates modular program design.
- The system analyst analyses the requirement of a program and divides it into a number of modules
- The specifications of each module, such as its functions, the calling methods, the parameters returned, are well defined
- Based on the specifications, the development of each module will be done by different programmers.
- Very useful to team work.
Steps:
- Obtain the requirements
- Design the program flow using flow chart
- Divide into modules
- Ask programmers to develop the modules
- Integrate the modules (write the Main Program and call all the modules)
Interface versus Implementation
A class stored in the header file is a contract between the system analyst and programmers, and between the developers and customers.
- System Analyst who wants to use objects of this class should follow the rules defined in the class declaration
- Class should be implemented by the programmer exactly the same way it is declared; otherwise, it will cause errors
In the language of OO programming, this contract is named as interface.
Create the library with Visual C++
Writing a Good Program
* - Value of
& - Address of
Pointers(Very Important Concept)
You need to be familarized with memory.
Memory is for storing executable code during executing.
How memory is used in C++?
The whole big piece of memory is divided into 4 areas:
-
Code Space - for the storage of program code
-
Stack - for the storage of local variables/objects, passed parameters.
-
Global Name Space - for the storage of global variables/objects
-
Free store - for the storage of dynamically created data
When a program start execute, the operation system will allocate a fixed memory for Code space, a fixed memory for Stack, a fixed memory for Global Name Space.
What is Free store / the Heap? - the memory remained unuse. Unused memory is dynamic.
to use the heap, you have to use pointer.
Only the Operating System know whether the particular memory is used in the free store or not.
What is the Address of a variable?
A variable uses a space in memory. Every variable has a memory address.
Each byte has an address, Each variable has the starting-byte address. All values written in hexadecimal but binary in reality.
Indicates Address using Reference (&)
In C++, use & ampersand to indicates the address of a variable.
Note Variable and address of a variable are different.
What is a Pointer?
In many situations, we want to store the address of a variable into a particular memory location.
- The value of pointer must be the address value.
In C++, every address has 4 bytes.
size of pointer must be 4 bytes long.
e.g. short is 2 bytes, but it’s address is still 4 bytes.
In C++, each variable/object must have its type/class declared.
The type of a pointer variable is understood as where the address is stored in the variable.
If we want to declare the type of pa, which stores the address of a char variable a, how do we do it?
1 | char *pa; // declaring pa (you get 4 bytes!); |
char *pa states that the memory content of the address stored in pa is a character. pa is indirectly declared to be a variable storing an address of a character.
Purpose of Pointer : allow programmer be able to use the memory in the free store.
Dont touch the pointer until you assign it a address!
1 | //Note: 0x30 is Understood in hex number |
More examples:
1 |
|
Why Pointer? - Using Free Store
Like we mentioned, Pointer allows us to handle memory in Free Store.
- The Free Store is opened to all functions
Pointer helps us to identify the part of memory in Free Store that is being used by a particular function or object.
To use the memory in Free Store:
- Claim to the system how much memory is required
- System allocates a memory space with size big enough
- System returns a pointer value which is the starting address of that memory space. (A pointer needs to store this value.)
- When the memory space is not required, release it back to the system for other functions.
new and delete
The keywords new and delete help us claim and release memory in Free Store.
Note: The number of new and number of delete must be same.
Example:
Part1
1 | unsigned short int * pPointer; //Local Pointer |
Part2
1 | int * pPointer2; |
The address of array is the address of first element in the array.
Note: delete ≠ remove a pointer, it still exists
Stray (Wild or Dangling) Pointers
If one deletes a pointer, the associated memory will be given back to system.
- If one tries to use that pointer again without reassigning it, the result is unpredictable
- To ensure one will not use the deleted heap memory again, always assign the pointer with 0 after delete
A stray (or wild, dangling) pointer is one that has been deleted but without assigning to NULL .
NULL pointer is safe, according to Operation System.
1 | int *pNum = new int(5); // Initialize *pNum to 5 |
Memory Leaks
The program below will introduce the problem of memory leaks (the system cannot get back the memory allocated to the program) and execution error. Build the program and step over each line of code using the Run- time Debugger.
1 |
|
- What is the address of localVar? (Use Visual Studio Debug mode to check)
- What is the value of pHeap after executing line 5? (0)
- What is the value of pHeap after executing line 11? (0)
- Assume that you can finish executing the program. Do you think you can free the memory claimed by the new statement in line 5? If no, why not?
Modify the program such that we can free the memory claimed by both new statements in line 5 and line 11.
Ans:
1 |
|
Creating Objects in the Free Store
We can also create objects in the Free Store.
1 | CAT *pCat = new CAT; |
pCat stores the starting address of the memory allocated.
When the object is created, its constructor is called.
Object identified by a pointer.
Note: Size of Class = All the member variable size (consecutively)
Deleting Objects
Objects in the Free Store can also be deleted.
1 | CAT *pCat = new CAT; //pCat becomes an identifier of the object created |
Example:
1 |
|
1 | int main(){ |
Result:
1 | SimpleCat Frisky... |
Accessing Members of Objects
To access members of an object, the operator (.) is used
1 | SimpleCat *pCat = new SimpleCat; |
In C++, a shorthand is provided for such member access.
1 | SimpleCat *pCat = new SimpleCat; |
Pointers Arithmetic
Pointers can be added or subtracted from one another if they are of the same type.
1 | short int *a, *b, x=0x100A; |
The same applies to objects.
You must not DIRECTLY assign a value to a pointer, e.g. int *p=0x00110110;
1 | Cat *a = new Cat; |
Arrays and Strings
What Is an Array?
An array consists of a collection of data storage locations, each holds the variables/objects of the same type/class.
An array can be easily declared as follows:
1 | short shortArray[25]; |
It states that there is a sequence of 25 short integer data. The whole sequence is named as shortArray.
Note: In consecutive memory.
Array Element
- In an array, an array element is referred to by indicating its index
- The first element has index 0, and then 1, …
- In our previous example,
shortArray[0]
is the first element andshortArray[24]
is the last element. - Do not try to use
shortArray[25]
, result unpredictable.
Initializing Arrays
An array can be initialized during declaration
1 | int IntegerArray[5] = {10,20,30,40,50}; |
Wrong example:
1 | int IncorrectArray[2] = {10,20,30}; //ERROR |
Note:
int a[5];
NOT the same asint a[5]={};
.
Array of Objects
Any object can be stored in an array.
Accessing member data in an array of objects is a two-step process.
- Identify the member of array by
[]
- Access the member by .
1 | CAT Litter[5]; //Litter[0] - Litter[4] are 5 objects |
Multidimensional Array
It is possible to have an array of more than 1 dimension.
1 | int SomeArray[5][2] = { {0,0},{1,2},{4,6},{7,2},{4,4}}; |
Array and Pointer
C++ allows the flexibility for user to use Array and Pointer interchangeably.
An array’s name can be regarded as a constant pointer pointing to the first element of the array.
1 | int a, b; //accquire 4x2 bytes in stack |
Compiler does all the calculation.
SomeArray+1
does not add 1 to SomeArray
but add 4 (1 integer needs 4 bytes for storage), and points to the next element in the array.
More about Pointers and Arrays
another example:
1 | int SomeArray[5]={10,20,30,40,50}; //accquire 4x5 bytes in stack |
Note in the above example,
px = &SomeArray;
is incorrect.Because there is NOT any memory location to store the pointer
SomeArray
. Everything is done by an internal conversion
another example:
1 | int SomeArray[5] = {10,11,12,13,14}; |
Those above examples are just demostration to let you realize the thing. This isn’t the propose of using pointer.
Directly Assign Value into a pointer array
1 |
|
Array of Pointers
So far the arrays are declared to store data in the stack.
Usually the memory space of stack is small
If a large array is required, it is better to store the elements of arrays in the Free Store (Heap).
In this case,for every element in an array, a pointer is assigned to indicate its location in the Free Store. This becomes an array of pointers.
1 |
|
Pointer of Array
If one feels that 500 pointers in the previous example are still too many, we can put the whole array into the Free Store
- Hence one pointer is enough to point to the array itself but not the individual element
- It becomes a pointer of array.
1 | CAT *Family = new CAT[500]; // 4 byte in stack, 500xobject byte in heap |
1 | int a = 0, b=0; |
String - char Array
A string is stored in an array of characters.
A string can be simply initialized as follows,
1 | char Greeting[] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'}; |
Note:
\0
The null character represents the end of string; it must be added.
However, this method can easily introduce errors.
C++ provides a shorthand that makes use of the double quote " ".
1 | char Greeting[] = {"Hello World"}; |
Do Not mix up string size with character array size!
string is the content stored in a character array.
Copying String
strcpy() and strncpy()
C++ inherits from C a library of functions for tackling strings
Two most common ones are
strcpy()
andstrncpy()
1 |
|
strcpy()
will overwrite past the end of the destination if the source were larger than the destination, damaging other data.
- To reduce the problem,
strncpy()
can be used
1 |
|
Strncpy()
needs another parameterMaxLength
which specifies the maximum no. of characters to be copied (NOT counting the null character).
A few more library functions
- To measure the length of a string, the function
strlen()
is useful- To combine two strings into one, we can use the function
strcat()
_itoa()
converts an integer into a stringitoa()
in older VS version)int atoi(char *)
converts a string to an integer
1 |
|
Command-Line Processing
In many operating systems, command-line options are allowed to input parameters to the program.
1 | $ SomeProgram Param1 Param2 Param3 |
To achieve this, main()
allows two input parameters to hold the command-line options.
1 | //main() is inside the project SomeProgram |
The values of
argc
,argv[]
are assigned automatically.
argc
stores the no. of strings entered by the user (other label can be used instead of argc.)
argv
is an array. Each element of the array is a character pointer
How this acutually work?
1 | $ SomeProgram Param1 Param2 Param3 |
In this case:
argc
= 4
argv[0]
points to “SomeProgram” : Noteargv[0][0]
is ‘S’
argv[1]
points to “Param1”
argv[2]
points to “Param2”
argv[3]
points to “Param3”
Look at this example:
1 | //cliprocessing.exe |
When you call the program through command prompt:
1 | $ cliprocessing a1 a2 b |
it should give you this result:
1 | Received 4 arguments. |
Parameter passing using pointers
Pass Parameters - Pass by Value
Look at this example “badswap”.
1 | //badswap.cpp |
To pass parameters to functions, we may pass parameters by value, i.e. pass copies of the parameter values to functions.
Pass by Reference
Look at this example “goodswap”.
1 | //goodswap.cpp |
Pointer allows pass parameters by reference.
Return Multiple Values
Normal function can only return ONE value.
If more than 1 value are to be returned, it can be done by passing 2 or more parameters to a function by reference.
1 |
|
Passing an array of parameters to a function
To save effort from separately passing a number of parameters to a function, they may be passed as an array.
1 |
|
Note that in the previous example, the string in
str[]
is modified inside the functionopt()
- It is because passing the name of an array has made the array elements to be passed by reference
- When copying the string “NewString” to
stringP[]
inopt()
, it is just the same as copying to the originalstr[]
.
str and stringP are the same by value.
Stream I/O
Input and Output
The input and output (I/O) are handled by the standard C++ library (such as iostream).
- A library is a collection of object code to be linked to the C++ program to provide additional functionality
- For different platforms, different libraries (that may use the same name) can be used for I/O functions
Buffering
- iostream classes view the flow of data as being a stream of data, one byte following another
- Buffer is provided in some cases to the stream
Standard I/O Objects
When a C++ program that includes the iostream classes starts, four objects are created and initialized.
Object | Usage |
---|---|
cin |
handle input from the standard input, i.e. keyboard |
cout |
handle output to the standard output, i.e. display |
cerr |
handle unbuffered output to the standard error device, i.e. display in a PC |
clog |
handle buffered error messages that are output to the standard error device, i.e. display in a PC. |
Buffered: Display only when a flush command is sent from the library code
Input using cin
cin
has been generally used for input data from keyboard
The operator >> is overloaded such that different type of data can be read into the buffer of cin and then to some variable.
Member functions
Function | Usage |
---|---|
cin.get() |
Helps to obtain the input data in a more flexible way. |
cin.getline() |
allows the whole line of data to be input to a character array |
Example of cin.get()
1 |
|
Why do we use cin.getline()?
cin >> abc
will stop to read in data if it sees, e.g. a space or a tab key.
cin.getline()
can only read in string, but not value of other types;However, it will not stop when encountering spaces or tabs.
Small Example :
1 |
|
Note that since cin>> leaves the newline character (\n) in the iostream. If getline is used after cin>>, the getline sees this newline character as leading whitespace, thinks it is finished and stops reading any further. To fix the problem, one of the solutions is to add cin.ignore() after cin.
1 | cin.ignore(100,'\n'); // skips up to 100 characters |
Another solution is to use cin.getline() to assure the keyboard buffer is empty. Then call cin.getline() the second time to do the job you want.
1 | cin.getline(dummy, 20); //Clear buffer |
Output with cout
Just as
cin
,cout
is also an object created when the iostream header file is compiled
- The operator << is overloaded such that different types of data can be sent out.
Member functions
Function | Usage |
---|---|
cout.put(char a) |
Put the character ato output, and return cout |
cout.write(char *buf,int length) |
Write length characters in buf[] to output device , and return cout. |
1 |
|
Other Member functions
Function | Usage |
---|---|
cout.width(int a) |
Set the width of the next output field to a’s value |
cout.fill(char b) |
Fill the empty field of the output by b’s value |
1 |
|
File Input and Output (Read or Write Files)
File access is usually done with steps as follows:
Step 1: Open file (To claim from the system the access of a particular file)
Step 2: Read data from file / Write data to file
Step 3: Close file (To indicate to the system the file access is finished (closed))
We use ofstream
and ifstream
to deal with files.
First you need to include the fstream
header file in your program.
1 |
To open a file for writing or reading, first create an ofstream
or ifstream
object respectively with the filename as the input parameter.
1 | ofstream fout("myfile.cpp"); |
After opening files, reading or writing files can be done in a similar way as cin
or cout
respectively.
After writing/reading, close the file using the member function
close()
of theofstream
/ifstream
objects.
Example Here:
1 |
|
Changing Default Behavior
Default behavior of opening a file by ofstream
is to create it if it doesn’t yet exist.
- If exists, it deletes all its contents and overwrite on it (truncate)
Use a second parameter to change the behavior.
1 | ofstream fout2("myfile.cpp",ios::app); |
Second Parameter | Usage |
---|---|
ios::trunc |
Default for ofstream ; truncates if it exists |
ios::app |
Append: File will be opened for appending data to the end of the existing file |
ios::ate |
Place the position at the end of the file (either input or output), but write data at the start position like trunc |
ios::in |
Overwrite: The file (if it exists) will NOT be truncated, the read/write cursor is positioned at the start of the file. |
Appending to the End of file
Example:
1 |
|
extra:
1 | . |
Editing File
It is often that we need to modify a particular part of a file - editing a file
ofstream
andifstream
offers 4 member functions that set the current position of an opened file.
For ofstream of ifstream ? |
Function | Usage |
---|---|---|
ofstream |
seepkp(long pos) |
sets the current position. pos is a byte offset from the file beginning |
ofstream |
tellp() |
tells the current position. Return a byte offset from the file beginning |
ifstream |
seepkp(long pos) |
sets the current position. pos is a byte offset from the file beginning |
ifstream |
tellg() |
tells the current position. Return a byte offset from the file beginning |
Example:
1 |
|