AllTutor Tutorial CPP Index - Asp
AllTutor Tutorial CPP Index - Asp
Introduction
C++ is an object-oriented programming language, developed in the early 1980's by Dr. Bjarne Stroustrup
from C. The original version was called, "C With Classes", as classes were the major extension to C to
add functionality to structures. The C programming language is a complete subset of C++.
Contents
● Getting Started.
● Basic Input/Output.
● Variables.
● Keywords.
● Operators.
● Formatting Input/Output.
● Constructs for Program Flow.
● Arrays.
● Functions.
● Pointers and Strings.
● Memory Allocation.
● Structures.
● File Handling.
● Command Line Arguments.
● Bitwise Manipulators.
Classes.
Organising Classes.
Constructors and Destructors.
Constant Objects and Member Functions.
Operator Overloading.
Friend Functions.
Inheritance.
Initialising Base Member Variables.
Multiple Inheritance.
Virtual Base Classes.
Pointers to Class Heirarchies.
Virtual Functions.
Abstract Classes.
Polymorphism.
Container Classes.
Filename
A source file is the file that contains the C++ code that is compiled into an executable file, using a C++
compiler. C++ source files usually have an extension name of cpp, or cxx, depending on the compiler.
Library Files
Like C, C++ has a limited number of keywords, and depends on Library Files for its functionality. For
example, C does not include any keywords for input or output. This functionality is achieved by using
library files. These library files are referred to as Header files and have a .h extension name. The
standard input/output header file is called iostream.h. The #include statement is used to insert the header
code so your program may use the functions defined in the header file. Angled brackets are used to
instruct the preprocessor to find the header files from the standard header file directory. The following
illustrates how to include the iostream.h file.
#include <iostream.h>
Comments
There are two types of comments in C++, Block Comments, and In-Line Comments.
Block Comments
Block comments span several lines. The characters /* start a block comment, and the characters */ end
the block comment.
/*
are provided.
*/
In-Line Comments
An in-line comment is a comment that is on a single line. Inline comments do not require termination
characters, as they're automatically terminated at the end of the line. The characters // are used to start
an inline comment.
Nested block comments are not allowed in C++. The following causes an error.
/*
*/
Inline comments may be nested within block comments, or even inline comments.
/*
*/
Preprocessor Directives
Before the program is compiled, the source code is scanned by a preprocessor to perform text
substitution, and header file inclusions. C++ supports inline functions, and constants, so is consequently
more often used just for header file inclusion and conditional compilation statements.
Preprocessor directives are preceded with a #. The # should always be placed in the first column of the
line. The following is a directive that causes the contents of the header file to be brought into the current
file, effectively replacing the directive line with the contents of that file.
#include <iostream.h>
Most C++ programs have one main( ) function, with the exception of Dynamic Link Libraries (DLL's) in
Windows. The main( ) function is the starting point of the program. The ANSII C++ definition for declaring
the main( ) function is either:
int main()
or
The second definition is used with Command Line Arguments and shall be covered later. The int keyword
means that the program should return an integer (whole number) to the operating system, signifying
success or failure. A return value of zero indicates success. Each statement within the main function or
any other functions should be tabbed in (indeneted) to show the structure. The braces are used to group
the statements within the function together.
first.cpp
#include <iostream.h>
int main()
return 0;
Input/Output
For basic input and output in C++, we shall cover the cout and cin functions provided by the iostream.h
header file.
The cout statement is used to place text on the screen. The stream insertion operator, << is capable of
handling all of the basic data types in a way that is transparent to the programmer.
The following example prints the string, "Hello Juicy", to the screen:
To output the integer i and the double d, seperated by a string, the following statement may be used:
Each item following the << characters is inserted onto the output stream without the programmer having
to specify their data types.
The escape sequences used by C are still used in C++, such as the '\n' character to produce a new line.
All escape sequences are preceded with a backslash. As a backslash denotes the start of an escape
sequence, an escape sequence is provided in order to print a backslash.
The following table lists the sequence characters that may be printed.
Escape Sequences
\n New line
\t Horizontal tab
\v vertical tab
\f Form feed
\a Alarm
\\ Print a backslash
The cin statement is used to get input fromt he keyboard. Like the stream insertion operator, the stream
exatraction operator, >> is capable of handling all of the basic data types in a way that is transparent to
the programmer. The following example uses the cin statement to place data entered from the keyboard
into the variable, i.
cin >> i;
The following example reads a value from the keyboard, assigns it to the variable num, and displays the
value.
getnum.cpp
#include <iostream.h>
int main()
int num;
cout << "The number your entered was " << num << endl;
return 0;
The above program requires a variable in which to store the value for num. The declaration, int num;
provides a temporary storage area called num that has a data type of integer (whole number).
All statements in C end with a semicolon. The following program accepts two numbers from the user,
storing them in the variables firstNum and secondNum. The numbers are added together and the result
is stored in a variable called result which is then output back to the user.
simpleadd.cpp
#include <iostream.h>
int main()
cout << "The sum of " << firstNum << " and " << secondNum << " is " <<
result << endl;
return 0;
Most programs require the temporary storage of data. The data is stored in a variable, which is a
temporary storage in the computer's memory. The variable name is the identifier used to identify the
data. The identifier is a sequence of characters that denotes the name of the variable to be used. The
identifier may consist of letters (a-z and A-Z), digits (0-9), and underscores. It must start with a letter or
an underscore. Variable declarations must be at the start of the function before any statements. The
following declares the variable num which has a data type of integer (whole number).
int num;
Unlike C, declarations in C++ are statements. As declarations are statements in C++, variables may be
declared anywhere within the program. In the following example, the scope of the variable counter is
valid for the duration of the compound statement, initialised by the counted loop.
If there is already a declaration of counter, earlier in the function, then it will not have scope until the
compound statement has been completed, whereby it will retain its original value before the counted loop
was executed.
The following basic data types are available in C++. The actual amount of storage space required is
dependent on the compiler and the operating system.
Data Types
unsigned char Stores a signed character. Useful with extended character sets
Constants
A constant value never changes. Constants are declared in C using the const keyword. In C++, an
external const declaration has static linkage, and is only visible within the same source file. The following
declaration declares a constant called x and assigned the value 6. Once set, the value of the constant x
cannot be changed.
const int x = 6;
C++ Keywords
The following keywords have been introduced into C++. A brief description is provided here, as they are
discussed in more detail in the appropriate sections.
Keywords
Keyword Description
asm Used to add assembly language into the source code, implementation specific.
friend Used to declare functions as friends of the class. Friend functions are not part of the class,
but have access to the private members.
private Implements data hiding by defining which parts of the class are not accessible from outside
the class.
protected Allows members to be accessed either by the class, or classes derived from this class.
public Defines which parts of the class are accessible from outside the class.
this An implicitly defined constant pointer for all members in a class, where the type of this is
the class itself.
try Used with error handling, a block of code to try that may cause an exception error.
C++ Operators
You are here: Home > Tutorials > C++ > Operators used in C++
New Operators
Operator Description
delete [] iPtr;
void Rectangle::display()
Arithmetic Operators
Operator Description
* Multiplication, or indirection.
/ Division.
result = ~a;
total = a + b;
difference = a - b;
product = a * b;
quotient = a / b;
remainder = a % b;
a++;
b--;
num = ++a;
num = --b;
Self Assignment
If an assignment is made that requires the value of the variable being assigned to, C++ offers a
convenient shortcut by placing the operator immediately before the assignment operator.
Relational Operators
Operator Description
Logical Operators
Operator Description
&& Logical And. For example, (x > 4 && y <= 10) will evaluate to true if x is greater than four
and y is less than or equal to ten.
|| Logical Or. For example, (x > 10 || y > 10) will evaluate to true if either x or y are greater
than ten.
Stream I/O
The Stream I/O class hierarchy is used for basic input/output with C++, as summarised by the following
diagram.
[D]
The low level I/O operations are defined in the streambuf class. The ios (I/O State) is derived from the
streambuf class, adding information about the state of the stream. It contains the format flags, skipws,
left, right, dec, oct, hex, etc, and other state information such as width, precision and fill.
The input stream istream and output stream ostream are derived from the ios class. The class istream
has the function declarations get, read, getline, gcount, peek, putback, seekg and tellg. The ostream
class has the function declarations put, write, seekp and tellp. The iostream class is derived from both
istream and ostream. The iostream has four standard streams, cin, cout, cerr and clog. All of the above
streams are defined with iostream.h.
The file handling streams are defined in the header file fstream.h. Both streams inherit the basic
functionality of their superclasses, but add extra functionality for opening and writing to files. The class
fstream inherits from iostream adding functionality to open files in input/output mode.
The format flags may be set using the ios class flags. The following example uses the hex, showbase,
and uppercase flags to show an integer as a hexadecimal number, using uppercase letters for the
hexadecimal characters.
hex.cpp
#include <iostream.h>
int main()
return 0;
0X2D
The stream is reset to the state before the setf function was called after the cout operation.
The ios class may also be used to determine the width, precision and fill character of a field.
The width function sets the minimum field witdth for output. The field is padded if the data output to the
field is not wide enough. If the data is too large for the field, it isn't truncated. The field is reset after the
first insertion.
The precision function sets the number of decimal places for a field. The effect is persistent, and must be
explicitly reset. If no precision is set, the default precision is 6.
The fill function is used to specify the fill character used to pad a field. The effect is persistent, and must
be explicitly reset. If no fill character is specified, a space character will be used by default.
width.cpp
#include <iostream.h>
int main()
double pi = 3.141592654;
cout.precision(4);
cout.width(12);
cout.fill('#');
// Change precision to 10
cout.precision(10);
return 0;
3.14159
#######3.142
3.141592654
I/O Manipulation
The header file, iomanip.h contains further functions that may be used to manipulate the I/O streams in C
++. The following example illustrates how to set the width, precision and fill characters as well as convert
to hex and oct.
manipulator.cpp
#include <iostream.h>
#include <iomanip.h>
int main()
double pi = 3.141592654;
cout << "hex: " << hex << num << endl;
cout << "oct: " << oct << num << endl;
cout << "dec: " << dec << num << endl;
cout << "When padded, the value " << setw(8) << num
cout << "And may be filled " << setw(8) << setfill('*')
return 0;
The setiosflags function may be used to explicitly set the ios flags. The following line may be used to left
align a field.
Structured programming is based around three basic constructs: Sequence, Selection and Iteration. The
Sequence construct is the simplest, whereby statements are executed in the order they're found in the
code.
Both the Selection and Iteration constructs require a Logical Test. Logical tests can be performed on
variables, literal values, calculations, and results of functions The test will evaluate to either true or false.
Selection Constructs
The Selection constructs are used when the flow of execution may flow down two or more paths.
The if Statement
The if statement is used to control the flow of execution down one of two or more paths, depending on
the result of a logical test. Further conditions may be specified with else if, should previous conditions be
false, and else may be used should none of the above be true. There is no semicolon at the end of an if
statement.
else
If more than one line should be executed should a condition be true, the lines should be enclosed within
curly braces.
if (x == 10)
Note: A common mistake is to use the assignment operator instead of the equality operator when
checking for equivalence. The following statement will always evaluate to True as x is assigned the value
10 which is a non-zero number.
if (x = 10)
When there are many conditions, the switch statement can be used if the values are discrete. The switch
statement is easier to read than multiple if statements when there are a large number of discrete values.
Iteration Constructs
The Iteration constructs are used when a block of code is required to be executed continually until a
condition is met.
Pre-Condition Loops
Pre-condition loops allow for a condition to be tested at the start of the loop. This type of loop is used
when you only want to execute the block of code should the condition be true. If there is more than one
line to be included in the iteration, it should be contained within curly braces.
A semicolon is not added to the end of the while statement. If one is added in error, then the block of
code will be executed exactly once. The following example uses a pre-condition loop to calculate the
factorial of a number (a number that is multiplied by every integer number below itself down to 1).
factorial.cpp
#include <iostream.h>
int main()
int num;
cout << "The factorial of " << num << " is: ";
factorial *= num--;
return 0;
Post-Condition Loops
Post-condition loops allow for a condition to be tested at the end of the loop. This type of loop is used
when you want to execute the block of code at least once and is often used for validation. If there is more
than one line to be included in the iteration, it should be contained within curly braces. The following
example uses a post-condition loop to ensure that a number is between 1 and 10.
validate.cpp
#include <iostream.h>
int main()
int num;
do
return 0;
Counted Loops
Counted loops are used when you know how many times you want to execute a statement or a list of
statements. A semicolon is not added to the end of the for statement. If one is added in error, then the
block of code will be executed exactly once. The following is the general syntax of a counted loop.
// List of statements
The parameters that the counted loop operates on are in three sections separated by semicolons. The
first section is for initialising any variables, the second section has the condition, and the third section has
any increments required to implement the loop. If more than one variable is to be used in either the
initialisation_section or the increment_section, then they are separated by commas. As declarations are
statements in C++, control variables may be declared in the initialisation section of the counted loop. The
condition must evaluate to either true or false. Compounded conditions must be created by using the
logical operators. The following counted loop prints the prime numbers (a number divisible only by itself
and 1) between 1 and a number enetered by the user.
prime.cpp
#include <iostream.h>
int main()
int num;
test = counter;
prime = 1;
if ((counter % test) == 0)
prime = 0;
if (prime == 1)
return 0;
Arrays in C++
You are here: Home > Tutorials > C++ > Arrays in C++
An array is a set of variables, represented by a single name. The individual variables are called elements
and are identified by index numbers. The following example declares an array with ten elements.
int x[10];
The first element in the array has an index number of zero. Therefore, the above array has ten elements,
indexed from zero to nine.
To access an individual element in the array, the index number follows the variable name in square
brackets. The variable can then be treated like any other variable in C++. The following example assigns
a value to the first element in the array.
x[0] = 16;
The following example prints the value of the third element in an array.
The following example reads a value from the keyboard into the last element of an array with ten
elements.
Arrays can be initialised like any other variables by assignment. As an array contains more than one
value, the individual values are placed in curly braces, and seperated with commas. The following
example initialeses a ten dimensional array with the first ten values of the three times table.
int x[10] = {3, 6, 9, 12, 15, 18, 21, 24, 27, 30};
int x[10];
x[0] = 3;
x[1] = 6;
x[2] = 9;
x[3] = 12;
x[4] = 15;
x[5] = 18;
x[6] = 21;
x[7] = 24;
x[8] = 27;
x[9] = 30;
As the array is indexed sequentially, we can use the for loop to display all the values of an array. The
following example displays all the values of an array. It then sorts the array into ascending order, and
displays the sorted array.
sort.cpp
#include <iostream.h>
#include <iomanip.h>
int main()
int counter;
cout << setw(7) << counter << setw(10) << x[counter] << endl;
x[inner] = x[outer];
x[outer] = temp;
cout << setw(7) << counter << setw(10) << x[counter] << endl;
return 0;
Multidimensional Arrays
An array can have more than one dimension. By allowing the array to have more than one dimension
provides greater flexibility. For example, spreadsheets are built on a two dimensional array; an array for
the rows, and an array for the columns. The following example uses a two dimensional array with two
rows, each containing five columns.
multi.cpp
#include <iostream.h>
#include <iomanip.h>
int main()
{2, 4, 6, 8, 10} };
return 0;
Functions in C++
You are here: Home > Tutorials > C++ > Functions in C++
Functions allow the programmer to modularise the program. All variables declared within functions are
called local variables, in that they are known only in the function to which they have been defined. Some
functions have a parameter list that provides a communication method between the function, and the
module that called the function. The parameters are also local variables, in that they are not available
outside of the function. The programs covered so far all have main, which is a function. The following
example uses a function called square which writes the square (a number multiplied by itself) of the
numbers between 1 and 10.
factorial.cpp
#include <iostream.h>
#include <iomanip.h>
// Function prototype
int main()
cout << "Square of " << setw(4) << counter << " is "
return 0;
int square(int x)
return x * x;
The function prototype, "square", declares a function that takes an integer parameter and returns an
integer. When the compiler reaches the function call to square in the main program, it is able to check the
function call against the function's definition. When the program reaches the line that calls the function
square, the program jumps to the function and executes that function before resuming its path through
the main program. Programs that do not have a return type should be declared using void. The Factorial
program is an example of a recursive function, a function that calls itself.
Pass by Value
Parameters to a function may either be pass by value, or pass by reference. If parameters are passed by
value, only a copy of the variable has been passed to the function. Any changes to the value will not be
reflected back to the calling function. The above function uses pass by value, as the square function
doesn't need to alter the value of the parameter passed to it. The program, Number To Words, is another
example of pass by value functions.
Default Arguments
C++ Allows you to specify default values for the arguments of functions. The default value is specified in
the function prototype and not the function definition, unless the function definition is also the declaration.
It is not necessary to assign a default value for every argument, but from the point the first default value
is defined, default values will be required for the remaining arguments of the function. The following are
valid function prototypes for functions with three arguments.
// No default arguments
If no default argument is provided, then the argument must be provided when the function is called.
Default values are specified from left to right, as shown in the following example.
default.cpp
#include <iostream.h>
int main()
display(); // Displays 0 0 0
display(23); // Displays 23 0 0
return 0;
Pass by Reference
A function that uses call-by-reference arguments reflects any changes to the values of the arguments to
the calling function. In traditional C, this is achieved by passing the address of the variable, and using
pointers to de-reference the arguments. C++ introduces a reference operator (&), that allows true call-by-
reference functions, eliminating the need to dereference arguments passed to the function. The
reference operator is placed before the variable name of arguments in the parameter list of the function.
The function can then be called without passing the address, and without dereferencing within the
function. The following example contains a function to swap two values. As the values require changing
swap.cpp
#include <iostream.h>
int main()
swap(x, y);
return 0;
int temp = x;
x = y;
y = temp;
Function Overloading
C++ allows both functions and operators to be overloaded. An overloaded function, is a function with the
same name as another function, but with different parameter types. This promotes programming
flexibility. Overloaded functions allow the following
For example, suppose we were required to find the product of two numbers, either of which may be of
type int or double. All we would have to do is write four functions, each with the same name and defined
to ensure that we get the correct result, regardless of the types of the arguments we use in the function
call. The appropriate function is selected depending on the data types of the parameters.
The compiler will then choose the appropriate function. From a readability point of view, function
overloading should only be used when the functionality is the same. Overloaded functions must adhere
to the following two rules:
1. The compiler does not use the return type of the function to distinguish between function
instances.
2. The argument list of each of the function instances must be different.
The following example overloads a swap function for integers, and floating point numbers.
overload.cpp
#include <iostream.h>
int main()
int i1 = 3, i2 = 5;
swap(i1, i2);
swap(f1, f2);
return 0;
int temp = a;
a = b;
b = temp;
float temp = a;
a = b;
b = temp;
Inline functions
An inline function is a request to the compiler to optimise the function call by substituting the function
called at the point where the function call is made. If the request is successful, the overhead associated
with a normal function call is eliminated. To make an inline function, the keyword, "inline" precedes the
function prototype and function definition. As it's just a request, there is no guarantee that the function will
be called inline.
Functions containing the following would not be suitable for an inline function:
● Static Variables
● Iteration Constructs
● A switch Statement
● Arrays
● Recursive calls to istelf
The following example uses an inline function to determine if a given year is a leap year. If the request is
successful, the function definition will be expanded in the main part of the program, eliminating the need
for a function call.
leap.cpp
#include <iostream.h>
// Prototype declaration
int main()
int year;
if (leap(year))
cout << "The year " << year << " is a leap year" << endl;
else
cout << "The year " << year << " is not a leap year" << endl;
return 0;
// Definition of leap
return 1;
return 0;
Pointers
Pointer variables contain memory addresses as their values. Whereas a normal variable contains a
specific value, a pointer contains the address of a variable that has a specific value. When declaring a
pointer, an asterisk is placed immediately before the pointer name.
Memory Address
The address of the memory location where the variable is stored can be found by placing an ampersand
in front of the variable name.
The following example prints the variable value, and the address in memory of that variable.
To assign the address of the variable "num" to the pointer "iPtr", you assign the address of the variable,
num, as in the following example.
iPtr = #
To find out what is stored at the address pointed to by iPtr, the variable needs to be dereferenced.
Dereferencing is achieved with the asterisk that the pointer was declared with.
deref.cpp
#include <iostream.h>
int main()
int *iPtr;
iPtr = #
return 0;
Character Strings
Most C++ compilers contain a String class, but for the purpose of this section, we will ignore it for the
moment. Strings in C++ may be implemented as an array of characters. For example, to store a name
you could declare a character array big enough to store the name, and then use the appropriate library
functions to manipulate the name.
name.cpp
#include <iostream.h>
int main()
cout << "The name you entered was " << name << endl;
return 0;
Arrays in C++ start with an index value of 0. A character array with the string "Fred" would have the
following values in the elements of the array.
name[0] = 'F';
name[1] = 'r';
name[2] = 'e';
name[3] = 'd';
name[4] = '\0';
The header file <string.h> contains some string manipulation routines. The following is a list of the
common string handling routines in C++.
length.cpp
#include <iostream.h>
#include <string.h>
int main()
char name[80];
int length;
length = strlen(name);
cout << "Your name has " << length << " characters\n";
return 0;
copystr.cpp
#include <iostream.h>
#include <string.h>
int main()
strcpy(second, first);
return 0;
The strcmp function is used to compare two strings together. The variable name of an array points to the
base address of that array. Therefore, if we try to compare two strings using the following, We would be
comparing two addresses, which would obviously never be the same as it's not possible to store two
values in the same location.
if (first == second)
The following example uses the strcmp function to compare two strings.
compare.cpp
#include <iostream.h>
#include <string.h>
int main()
if (strcmp(first, second) == 0)
else
return 0;
concatenate.cpp
#include <iostream.h>
#include <string.h>
int main()
strcat(first, second);
cout << "The two strings joined together: " << first << endl;
return 0;
The strtok function is used to find the next token in a string. The token is specified by a list of possible
delimiters. The following example reads a line of text from a file and determines a word using the
delimiters, space, tab, and new line. Each word is then displayed on a seperate line.
token.cpp
#include <iostream.h>
#include <fstream.h>
#include <string.h>
int main()
char line[80];
char *token;
ifstream in("c:\\programming\\cpp\\text.txt");
if (!in)
return 0;
while(!in.eof())
in.getline(line, 80);
in.close();
return 0;
C++ provides the new and delete operators for memory allocation, instead of using C's malloc and free
functions. They cannot be interchanged with each other. For example, it's not possible to free memory
allocated by malloc with delete, and it's not possible to delete memory allocated by new with the free
function.
Allocating Memory
Memory allocation is achieved using the new operator. The following allocates memory for one an
integer, and sets the initial value to 42.
newint.cpp
#include <iostream.h>
int main()
int *iPtr;
delete iPtr;
return 0;
The memory allocated with new is released using the delete keyword.
When allocating memory for an array, the size of the array is specified within square brackets using the
new operator. The next example allocates memory for five integers.
fiveint.cpp
#include <iostream.h>
int main()
int *iPtr;
iPtr[counter] = 0;
delete [] iPtr;
return 0;
When deleting an array, the [] token must prefix the array name to delete. When allocating arrays, it's a
good idea to check that it was successful. If the memory is unable to be allocated, new returns a NULL
value.
checkmem.cpp
#include <iostream.h>
int main()
double *dPtr;
else
delete [] dPtr;
return 0;
Structures in C++
You are here: Home > Tutorials > C++ > Data Structures in C++
As well as the basic data types, C++ has a structure mechanism that allows you to group data items that
are related to each other under a common name. This is commonly referred to as a User Defined Type.
The keyword struct starts the structure definition, and a tag gives the unique name to the structure. The
data types and variable names added to the structure are members of the structure. The result is a
structure template that may be used as a type specifier. The following is a structure with a tag of month.
struct month
char name[10];
char abbrev[4];
int days;
};
Having defined the structure, you can declare an instance of it and assign values to the members using
the "dot" notation. Unlike C, an instance of a user defined type may be declared using the tag name. The
following example illustrates the use of the month structure.
month.cpp
#include <iostream.h>
#include <string.h>
struct month
char name[10];
char abbreviation[4];
int days;
};
int main()
month m;
strcpy(m.name, "January");
strcpy(m.abbreviation, "Jan");
m.days = 31;
<< m.abbreviation
<< " and has " << m.days << " days\n";
return 0;
All ANSI C++ compilers allow you to assign one structure to another, performing a member-wise copy. If
we had month structures called m1 and m2, then we could assign the values from m1 to m2 with:
m2 = m1;
Member Functions
C++ allows function declarations and definitions to be be included in the structure, to allow data and
behaviour to be encapsulated into a single entity. The following example adds a member function called,
"display" to a date structure.
displaydate.cpp
#include <iostream.h>
struct date
// Data members
int day;
int month;
int year;
// Member functions
void display() { cout << day << "/" << month << "/" << year << endl; }
};
int main()
date d;
d.day = 20;
d.month = 1;
d.year = 1964;
d.display();
return 0;
Member functions maybe defined outside the structure, by using the name of the structure, followed by a
scope resolution operator, followed by the name of the member function. The scope resolution operator
in C++ is, ::. The following example uses a scope resolution operator and defines the member function
display outside of the structure. In this example, the function has been declared as inline, but any
function may be declared outside the structure in the same way.
scopedate.cpp
#include <iostream.h>
#include <iomanip.h>
struct date
// Data members
int day;
int month;
int year;
// Member functions
void display();
};
void date::display()
int main()
date d;
d.day = 20;
d.month = 1;
d.year = 1964;
d.display();
return 0;
Unlike C, C++ allows to specify the visibility for the members of the structure. Access is restricted in C++
using the private, public and protected keywords. For the moment, we shall just concentrate on the
private and public keywords. By default, all members of a C++ structure are public. This means that all
data members and member functions are accessible outside of the structure. In order to restrict access
to the members of a structure, the keywords private and public are used. Members of a structure
declared following the keyword, private, are only accessible by member functions of the structure.
Members of a structure declared following the keyword, public, are accessible anywhere. The following
example uses a time structure, whereby the data members are not accessible outside of the structure.
Member functions are required in order to access the data members.
displaytime.cpp
#include <iostream.h>
#include <iomanip.h>
struct time
private:
// Data members
int hour;
int minute;
int second;
public:
// Member functions
void display();
};
void time::display()
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
int main()
time t;
t.set(13, 2, 4);
t.display();
return 0;
In the above example, the data members are declared private. This means that the data members
cannot be accessed directly. The following would result in a compilation error as it's attempting to access
a private member in the structure:
t.hour = 16;
Controlling access to the data members in this way allows us to ensure that the data members never
contain invalid values.
A file in C++ is a sequence of bytes. When a file is opened, a stream object is associated with the
filename. The header file fstream.h contains the the definitions for the stream classes ofstream (output
file stream), ifstream (input file stream), and fstream (input/output file stream).
The ofstream constructor may be used to create a sequential file. The constructor can take two
arguments, the name of the file, and the mode to open the file. The following example opens the file, junk.
txt, for output.
The mode, ios::out, is the default mode for the ofstream object, the file could have been opened with:
ofstream outFile("junk.txt");
An ofstream object may also be created without opening a file. The file to be opened may be associated
with the stream object later, as in the following example.
ofstream outFile;
outFile.open("junk.txt", ios::out);
The following is list of file open modes used with C++ File Streams.
Mode Description
ios::ate Open the file and move to the end. Data may be written anywhere in the file
ios::out Open the file for output. If the file exists, it will be overwritten
The ! operator is overloaded to test for errors opening the file. Data is written to the file using the insertion
operator. The following creates a file called junk.txt, and writes some information to the file.
create.cpp
#include <iostream.h>
#include <fstream.h>
int main()
char name[80];
if (!outFile)
return 1;
outFile << "This file was created by " << name << endl;
outFile.close();
return 0;
To read data from a sequential file is simple a case of opening the file, and using the extraction operator
to read the contents. The following example opens the file for reading, reads each word from the file, and
writes each word read on a new line.
read.cpp
#include <iostream.h>
#include <fstream.h>
int main()
char buffer[80];
if (!inFile)
return 1;
inFile.close();
return 0;
The content of the file could be organised as records. For example, consider the following file, containing
the forename, surname, and balance of a list of customers:
The following could be used to read the forename, surname and balance from the file.
record.cpp
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
int main()
float balance;
if (!inFile)
return 1;
inFile.close();
return 0;
The ANSI definition for declaring the main( ) function in C/C++ is either:
int main()
or
The second version allows arguments to be passed from the command line. The parameter argc is an
argument counter and contains the number of parameters passed from the command line. The
parameter argv is the argument vector which is an array of pointers to strings that represent the actual
parameters passed. The following example allows any number of arguments to be passed from the
command line and prints them out. argv[0] is the actual program. The program must be run from a
command prompt.
argdisplay.cpp
#include <iostream.h>
int counter;
return 0;
If the program is compiled into argdisplay.exe, it could be called as follows from the command line.
The next example uses the file handling routines to copy a text file to a new file. (eg, txtcpy one.txt two.
txt).
txtcopy.cpp
#include <iostream.h>
#include <fstream.h>
char buffer[80];
ifstream inFile;
ofstream outFile;
if (argc < 3)
return 0;
inFile.open(argv[1], ios::in);
if (!inFile)
cout << "Unable to open the file " << argv[1] << endl;
return 1;
outFile.open(argv[2], ios::out);
if (!outFile)
cout << "Unable to open the file " << argv[2] << endl;
return 1;
while (!inFile.eof())
inFile.getline(buffer, 80);
inFile.close();
outFile.close();
return 0;
At a hardware level, data is represented as binary numbers (1's and 0's). The binary representation of
the number 59 is 111011. Bit 0 is the least significant bit, and in this case bit 5 is the most significant bit.
Each bit set is calculated as 2 to the power of the bit set. Bitwise operators allow you to manipulate
integer variables at bit level.
bit 5 4 3 2 1 0
2 power n 32 16 8 4 2 1
set 1 1 1 0 1 1
With three bits, it is possible to represent the numbers 0 to 7. The following table shows the numbers 0 to
7 in their binary form.
Binary Digits
Binary Decimal
000 0
001 1
010 2
011 3
100 4
101 5
110 6
111 7
The following table lists the bitwise operators that may be used to manipulate binary numbers.
Binary Digits
Operator Description
| Bitwise OR
^ Bitwise Exclusive OR
~ Bitwise Compliement
Bitwise And
The bitwise And is True only if both bits are set. The following shows the result of a bitwise And on the
numbers 23 and 12.
10111 (23)
_____
00100 (result = 4)
You can use a mask value to check if certain bits have been set. If we wanted to check whether bits 1
and 3 were set, we could mask the number with 10 (the value if bits 1 and 3) and test the result against
the mask.
bittest.cpp
#include <iostream.h>
int main()
else
return 0;
Bitwise Or
The bitwise Or is True if either bits are set. The following shows the result of a bitwise Or on the numbers
23 and 12.
10111 (23)
01100 (12) Or
_____
You can use a mask to ensure a bit or bits have been set. The following example ensures bit 2 is set.
setbit.cpp
#include <iostream.h>
int main()
num |= mask;
cout << "After ensuring bit 2 is set: " << num << endl;
return 0;
Bitwise Exclusive Or
The bitwise Exclusive OR is True if either bits are set, but not both. The following shows the result of a
bitwise Exclusive Or on the numbers 23 and 12.
10111 (23)
_____
The Exclusive Or has some interesting properties. If you Exclusive Or a number by itself, it sets itself to
zero as the zero's will remain zero and the one's can't both be set so are set to zero. As a result of this, if
you Exclusive Or a number with another number, then Exclusive Or the result with the other number
again, the result is the original number. You can try this with the numbers used in the above example.
23 XOR 12 = 27
27 XOR 12 = 23
27 XOR 23 = 12
This feature can be used for encryption. The following program uses an encryption key of 23 to illustrate
the property on a number entered by the user.
encrypt.cpp
#include <iostream.h>
int main()
num ^= key;
cout << "Exclusive OR with " << key << " gives " << num << endl;
num ^= key;
cout << "Exclusive OR with " << key << " gives " << num << endl;
return 0;
Bitwise Compliment
The bitwise Compliment is a one's compliment operator that toggles the bit on or off. If it's 1, it will be set
to 0, if it's 0 it will be set to 1.
compliment.cpp
#include <iostream.h>
int main()
cout << "The compliment of " << num << " is " << ~num << endl;
return 0;
The Bitwise Shift Left operator shifts the number left. The most significant bits are lost as the number
moves left, and the vacated least significant bits are zero. The following shows the binary representation
of 43.
By shifting the bits to the left, we lose the most significant bit (in this case, a zero), and the number is
padded with a zero at the least significant bit. The following is the resulting number.
The Bitwise Shift Right operator shifts the number right. Zero is introduced to the vacated most significant
bits, and the vacated least significant bits are lost. The following shows the binary representation of the
number 43.
By shifting the bits to the right, we lose the least significant bit (in this case, a one), and the number is
padded with a zero at the most significant bit. The following is the resulting number.
The following program uses the Bitwise Shift Right and Bitwise And to display a number as a 16-bit
binary number. The number is shifted right successively from 16 down to zero and Bitwise And'ed with 1
to see if the bit is set. An alternative method would be to use successive masks with the Bitwise Or
operator.
binary.cpp
#include <iostream.h>
int main()
return 0;
Classes in C++
You are here: Home > Tutorials > C++ > C++ Classes
C++ is an Object-Oriented programming language. Objects are classified in C++ using a class to
encapsulate the data and behaviour of the object. Like other object-oriented programming languages, the
data of the object is hidden from the rest of the system, and made available through the services of the
class. Classes are defined in C++ using the class keyword.
class ClassName
};
Defining Visibility
By default, members of a class are defined with private visibility. This means that the members are not
accessible directly through the class. Although members are defined private by default, it's good practice
to explicitly define which members are private, and which members are public. As a rule of thumb, the
attributes (data) of the class are normally defined as private. The methods of the class are used to
access them. This ensures the integrity of the class and is one of the major strengths of Object-Oriented
Programming. The following example defines a class called, Time, with the attributes hour, minute, and
second.
class Time
private:
int hour;
int minute;
int second;
};
As the attributes are not accessible outside of the class, member functions are required to manipulate the
attributes. The member functions are defined with public visibility, meaning they may be accessed from
outside the class. This isn't always the case, as you may want to include member functions that may only
be called within the class, in which case they would be defined as private. The following extends the
Time class to include methods to display, and set the time.
class Time
private:
int hour;
int minute;
int second;
public:
void display();
};
The member functions may either be defined within the class, or outside the class. The following
example defines the display function within the Time class.
class Time
private:
int hour;
int minute;
int second;
public:
void display()
};
This implicitly defines the display method as an inline function. To define functions outside the class
requires a scope resolution operator. The function is defined like any other function in C++, but with
prefixed by the class name and a scope resolution operator, ::. The following is the set function defined
outside of the class.
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
In order to use the class, an instance must be created. An instance of the class is created by defining an
instance name following the class name. The following creates an instance of the Time class, called "t".
Time t;
The instance "t" may now be manipulated by using the methods of the class. The methods of the class
are accessed using the dot operator, (or -> operator if the class is defined as a pointer), similar to
structures. The following calls the set method to set the time to 13:02:04, and then the display function to
display the time.
t.set(13, 2, 4);
t.display();
classtime.cpp
#include <iostream.h>
#include <iomanip.h>
class Time
private:
int hour;
int minute;
int second;
public:
void display()
};
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
int main()
Time t;
t.set(13, 2, 4);
t.display();
return 0;
One of the major benefits of an object oriented approach, is reusability. Once a class has been defined, it
may be used in other projects without modification. To facilitate reusability, it's good practice to put the
class, and the definition of the methods of the class in different files. To illustrate this, the following
example contains three files, date.h, date.cpp, and usedate.cpp. The file date.h contains the definition of
the class Date. The file date.cpp defines the methods used in the class date.h. The file usedate.cpp uses
the class Date.
The class header file contains the class itself. This header file will be included in each file that uses it, so
preprocessor directives have been used to ensure it's only defined once.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
#include <iomanip.h>
class Date
private:
int day;
int month;
int year;
public:
void validate();
void display()
};
#endif
Any methods that are not defined within the class are defined within this file. This file is linked with files
that will use it, to provide the functionality of the class.
date.cpp
#include <iostream.h>
#include "date.h"
day = d;
month = m;
year = y;
validate();
void Date::validate()
if (month < 1)
month = 1;
month = 12;
if (day < 1)
day = 1;
else
day = 31;
break;
day = 30;
break;
day = 29;
else
day = 28;
Finally, the source file that will use the class includes the class as a header file, and is linked with the
source file for the class.
usedate.cpp
#include <iostream.h>
#include "date.h"
int main()
d1.set(20, 1, 1964);
d1.display();
d2.set();
d2.display();
d3.set(44, 2);
d3.display();
return 0;
Constructors and a destructors are sepcial functions that have the same name as the class to which they
belong. The purpose of a constructor is to help initialise the object, and the purpose of a destructor is
help destroy the object by making sure that memory is released. Constructors and destructors must not
define a return type.
1. Constructors
2. Default Constructor
3. Initialisation Lists
4. Copy Constructor
5. Destructors
Constructors
When the class is created, the constructor is called to initialise the object. The constructor may be
overloaded, in which case the most appropriate constructor is selected when the object is initialised. The
following example has a constructor to help initialise the Date class. When an instance of the class is
created, it calls the set function to set the day, month, and year.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
#include <iomanip.h>
class Date
private:
int day;
int month;
int year;
public:
// Class constructor
void validate();
void display()
};
#endif
An instance of the class Date must now be created using the appropriate arguments for the constructor,
as in the following example.
A default constructor is a constructor that may be called without any parameters. This may be achieved
by either providing default arguments for the constructor, or overloading the constructor with another
constructor that has no arguments. The following example creates a default constructor by providing
default values for the arguments.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
#include <iomanip.h>
class Date
private:
int day;
int month;
int year;
public:
// Default constructor
void validate();
void display()
};
#endif
The following declarations are all valid for the Date class.
Initialisation Lists
Initialisation lists provide an alternative method of initialising an object. The initialisation lists contains a
list of the attributes with the initial value in parenthesis, seperated by commas. The constructor in the
following example has been amended to use an initialisation list.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
#include <iomanip.h>
class Date
private:
int day;
int month;
int year;
public:
// Initialisation List
void validate();
void display()
};
#endif
Copy Constructors
Before looking at the copy constructor, it's important to understand the difference between initialisation
and assignment. Initialisation occurs when an object is created, and assignment occurs when an
assignment operator is used in an expression to set a previously defined object to a value.
Date d3;
d3 = d1; // Assignment
In the above example, each member of the instance d1 is copied to the instance d2, a process called
memberwise initialisation. A copy constructor is a special type of constructor that is used to initialise the
class object, to the value of another class object of the same class. The copy constructor is like any other
constructors, but has a reference to the object to be copied as its parameter. The following example
defines a copy constructor for the date cass.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
#include <iomanip.h>
class Date
private:
int day;
int month;
int year;
public:
// Default constructor
// Copy Constructor
day = copy.day;
month = copy.month;
year = copy.year;
void validate();
void display()
};
#endif
The copy constructor may be called implicitly when an object is initialised to another object, or explicitly
by passing the object to be copied as a parameter. The following example illustrates the two methods.
In this particular example, memberwise initialisation would have been sufficient. Our copy constructor
merely performs a memberwise initialisation so isn't really required. When data members are more
complex data objects, relying on the memberwise initialisation process may result in errors.
Destructors
Destructors are used to help destroy objects. Destructors are named after the class in the same way as
constructors, but the destructor name is prefixed with a tilde (~). Destructors enable the programmer to
ensure that all objects are destroyed properly, by releasing memory, closing files, updating databases,
etc. The following example defines a class called Client, and uses a destructor to release the memory
reserved for the client's name.
client.cpp
#include <iostream.h>
#include <string.h>
class Client
private:
char *forename;
char *surname;
double balance;
public:
// Default constructor
// Destructor
~Client();
void display();
};
strcpy(forename, f);
strcpy(surname, s);
balance = b;
Client::~Client()
// Tidy up
delete [] forename;
delete [] surname;
void Client::display()
int main()
c.display();
return 0;
Good class design involves writing classes whereby access is limited to the least amount required to
make the object workable. Defining attributes private ensures they may not be altered outside of the
class. C++ also offers the "const" keyword to ensure that objects or member functions may not be
altered.
Constant Objects
If an instance of a class is defined as constant, any attempt to modify the instance will result in a
compilation error. This is useful for objects that should not be modified, as it saves potential problems
being discovered at run-time. The following example creates an instance of the class Date, that cannot
be modified.
A constant member function is a function that doesn't change the data of the class. Any attempt by the
function to modify the class will result in a compilation error. This includes other functions that the
constant function may call. To make a function a constant function, the keyword, const, must be used in
both the function prototype and the function definition. In the Time class, the display function doesn't, and
shouldn't alter the data of the class. The following example makes the display function a constant
function.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
#include <iomanip.h>
class Date
private:
int day;
int month;
int year;
public:
// Default constructor
void validate();
};
#endif
Operator overloading is a special case of function overloading, which allows us to assign additional
meanings to most of the standard C++ operators. When overloading operators, it's good practice to
ensure that the overloaded operator has a similar behaviour to the original operator. For example, it
would make more sense to use the + operator for concatenation of strings than the = operator.
Overloading operators does not change the precedence and associativity of the operator. New operators
cannot be introduced using operator overloading.
When an overloaded operator function is a class member, it always has one item less in its argument list
than there are operands of the overloaded operator. The left operand is passed implicitly to the operator
function by means of the "this" pointer and the right operand is copied explicitly to the function's
parameter.
If an operator function is not a class member, it always has the same number of operands as the
overloaded operator. In the case of binary operators, this means that the definition of the operator will
have two items. Non-member operator functions do not require the left operator to be a class object, but
at least one operand must be a class object.
Basic Operators
! ~ + - * & / % << >> < <= > >= == != ^ | && || += -= *= /= %= &= ^= |= <<= >>= , ->* -> () [] = ++ -- new
delete
Some of the operators have both unary and binary forms. For example, the + operator may be unary
+10, or binary x + 10. Both the unary and binary forms of the following operators may be overloaded.
+-*&
. .* :: ?:
The following example overloads the += operator, to allow two times to be added together.
time.h
#ifndef GL_TIME_H
#define GL_TIME_H
#include <iostream.h>
#include <iomanip.h>
class Time
private:
int hour;
int minute;
int second;
public:
// Default constructor
};
#endif
The following are the definitions of the methods for the class, Time.
time.cpp
#include <iostream.h>
#include "time.h"
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
usetime.cpp
#include <iostream.h>
#include "time.h"
int main()
t1 += t2;
t1.display();
return 0;
Unary operator overloading has one operand rather than two. As with binary operator overloading, if the
operator function is a class member, then there is one less item than there is in the overloaded operator.
The following example extends the Time class to overload the unary ++ operator. Because the prefix and
postfix operators ++ and -- are available in two forms, two versions of the overloaded operator are
required. Specifying a parameter of int to the overloaded function is required to make it a postfix
operator.
time.h
#ifndef GL_TIME_H
#define GL_TIME_H
#include <iostream.h>
#include <iomanip.h>
class Time
private:
int hour;
int minute;
int second;
public:
// Default constructor
void operator++();
void operator++(int);
};
#endif
The following are the definitions of the methods for the class, Time.
time.cpp
#include <iostream.h>
#include "time.h"
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
usetime.cpp
#include <iostream.h>
#include "time.h"
int main()
Time t;
t++;
t.display();
return 0;
A friend function is not a member of the class, but has access to the non-public members of the class. In
general, friend functions are frowned upon in C++ because it breaks the natural encapsulation. As a
general rule, you should pick your friends with care, as you don't want just anyone tinkering with your
private parts. One of the best use of friend functions is with operator overloading.
The following example defines a friend function to overload the C++ output operator. As the operator is a
friend of the class, it has access to the private members, replacing the need for a display function.
date.h
#ifndef GL_DATE_H
#define GL_DATE_H
#include <iostream.h>
class Date
private:
int day;
int month;
int year;
public:
// Default constructor
void validate();
};
#endif
date.cpp
#include <iostream.h>
#include "date.h"
return o;
day = d;
month = m;
year = y;
validate();
void Date::validate()
if (month < 1)
month = 1;
month = 12;
if (day < 1)
day = 1;
else
day = 31;
break;
day = 30;
break;
day = 29;
else
day = 28;
usedate.cpp
#include <iostream.h>
#include "date.h"
int main()
Date d;
d.set(20, 1, 1964);
return 0;
Inhertiance C++
You are here: Home > Tutorials > C++ > Inheritance in C++
An object-oriented approach to software development involves building classes based on other classes in order to
create well defined classes. The base class is the lowest common denominator, and is used to derive further classes
from it. A base class typically has the common elements, and derived classes extend these elements to fully define the
class. The base class is the class at the root of the inheritance diagram. Classes derived from this class are known as
subclasses. Subclasses themselves may contain further subclasses. The parent of a subclass is referred to as the
superclass.
Protected Members
So far we have defined members of the class as private and public. Members of the class with private scope are not
accessible outside of the class. Members of the class with public scope are accessible outside the class. When
deriving a class, a mechanism is required that restricts access to the member to enforce encapsulation, but allows the
members to be visible when derived. This is achieved in C++ by defining them as protected. They are still not
accessible from outside the class, but are visible in classes derived from the class.
Clock Example
A digital clock is a special case of a clock. The basic data is that of a clock, but a digital clock may store tens of a
second for example. As it shares information in common with a clock, the class Digital could be derived from the class
Clock. The following example shows the UML class diagram for this arrangement.
[D]
Public Inheritance
Derived classes using public inheritance, inherit the public and protected members of the superclass. Private
members, and friend functions are not inherited. In C++, public inheritance is achieved by specifying the class it's
derived from, as in the following example.
clock.h
#ifndef GL_CLOCK_H
#define GL_CLOCK_H
#include <iostream.h>
#include <iomanip.h>
class Clock
protected:
int hour;
int minute;
int second;
public:
// Default constructor
};
#endif
clock.cpp
#include <iostream.h>
#include "clock.h"
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
digital.h
#ifndef GL_DIGITAL_H
#define GL_DIGITAL_H
#include <iostream.h>
#include <iomanip.h>
#include "clock.h"
protected:
int tensSeconds;
public:
// Default constructor
Digital(int h=0, int m=0, int s=0, int t=0) { set(h, m, s, t); }
};
#endif
digital.cpp
#include <iostream.h>
#include "digital.h"
tensSeconds = t % 10;
s += t / 10;
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
useclock.cpp
#include <iostream.h>
#include "date.h"
#include "digital.h"
int main()
Clock c;
Digital d;
c.display();
d.display();
return 0;
When creating instances of a class where there is a constructor, the base class constructor may be used
to supply the values for the core attributes. When a class is derived from a base class, the base class is
also created. C++ allows you to explicitly call the base class to initialise attributes, by specifying the class
name as a constructor following the derived constructor.
Digital(int h=0, int m=0, int s=0, int t=0) : Clock(h, m, s) { tensSeconds
= t; }
The following example initialises the Digital clock by calling the base class constructor.
clock.h
#ifndef GL_CLOCK_H
#define GL_CLOCK_H
#include <iostream.h>
#include <iomanip.h>
class Clock
protected:
int hour;
int minute;
int second;
public:
// Default constructor
};
#endif
clock.cpp
#include <iostream.h>
#include "clock.h"
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
digital.h
#ifndef GL_DIGITAL_H
#define GL_DIGITAL_H
#include <iostream.h>
#include <iomanip.h>
#include "clock.h"
protected:
int tensSeconds;
public:
// Default constructor
};
#endif
digital.cpp
#include <iostream.h>
#include "digital.h"
tensSeconds = t % 10;
s += t / 10;
second = s % 60;
m += s / 60;
minute = m % 60;
h += m / 60;
hour = h % 24;
useclock.cpp
#include <iostream.h>
#include "date.h"
#include "digital.h"
int main()
Clock c;
Digital d;
c.display();
d.display();
return 0;
Multiple Inheritance
You are here: Home > Tutorials > C++ > Multiple inheritance in C++
Multiple inheritance occurs when a class is derived from more than one class. Each class to be derived
from is listed after the class name, separated by commas. The classes are inherited from left to right. In
the following example, class C is derived from both class A and class B.
The example in this tutorial derives a class called "Grid" from the classes "Letter" and "Number". The
following diagram illustrates the arrangement of the classes. See the Object Oriented Analysis and
Design tutorial for more information on class diagrams.
[D]
letter.h
#ifndef LETTER_H
#define LETTER_H
class Letter
protected:
char ch;
public:
};
#endif
number.h
#ifndef NUMBER_H
#define NUMBER_H
class Number
protected:
int num;
public:
};
#endif
The grid class is defined in grid.h, and inherits from both the Letter class, and the Number class. The
overloaded friend operator is defined in grid.cpp.
grid.h
#ifndef GRID_H
#define GRID_H
#include "letter.h"
#include "number.h"
public:
};
#endif
grid.cpp
#include <iostream.h>
#include "grid.h"
o << "[" << g.ch << ", " << g.num << "]";
return o;
usegrid.cpp
#include <iostream.h>
#include "grid.h"
int main()
return 0;
When a class is indirectly derived from the same base class, a problem may occur. This type of multiple
inheritance is called overlapping inheritance, and is illustrated by the following example.
commonbase.cpp
#include <iostream.h>
class CommonBase
public:
int x;
};
public:
int y;
};
public:
int z;
};
public:
cout << "Values are: " << x << ", " << y
};
int main()
Overlapping ov;
ov.x = 1;
ov.y = 2;
ov.z = 3;
ov.Display();
return 0;
The problem with the above example is that there is an ambiguous reference to the variable x defined in
the CommonBase class. The definition "ov" creates two instances of the class CommonBase, one for
DeriveCommonA, and another for DeriveCommonB. The compiler is unable to resolve x, and results in
an error message.
Derive as Virtual
The problem is resolved by declaring the base class "CommonBase" as virtual in each of the derived
classes DeriveCommonA and DeriveCommonB. This causes the two derived classes to share a single
instance of CommonBase, rather than ambiguous multiple instances. The following example fixes the
problem.
virtual.cpp
#include <iostream.h>
class CommonBase
public:
int x;
};
public:
int y;
};
public:
int z;
};
public:
cout << "Values are: " << x << ", " << y
};
int main()
Overlapping ov;
ov.x = 1;
ov.y = 2;
ov.z = 3;
ov.Display();
return 0;
You can define a pointer to a class by assigning the pointer the address of the instance of the class.
SomeClass instance;
Coordinate Example
The following example illustrates using class pointers, using a Coordinate class.
Coordinate Class
coordinate.h
#ifndef COORDINATE_H
#define COORDINATE_H
class Coordinate
protected:
int x;
int y;
public:
};
#endif
coordinate.cpp
#include <iostream.h>
#include "coordinate.h"
Coordinate::Coordinate(int a, int b)
Set(a, b);
x = a;
y = b;
o << '[' << c.x << ", " << c.y << ']';
return o;
usecoord.cpp
#include <iostream.h>
#include "coordinate.h"
int main()
Coordinate c;
c_ptr->Set(1, 2);
return 0;
Virtual Functions
You are here: Home > Tutorials > C++ > Virtual Functions
A pointer, to a base class, may be used to point to any class derived from that object. Polymorphism is
achieved by using this method. As derived classes are distinct from their base classes, a pointer to a
derived class may not be used to access the base class without an explicit and unambiguous type
conversion.
SomeClass instance;
DerivedClass derivedInstance;
c_ptr = &derivedInstance;
Dynamic Binding
Redefinitions of a virtual function override the definition in the base class rather than overload it. This is
because the resolution of the function is decided at run-time rather than during the compilation. If a
pointer to a base class object is assigned the address of a derived class object, the pointer remains
pointing to the base class members and can only be used to access the base class members. In the
above example, c_ptr still points to the members of the base class, even though it has been assigned to
the derived instance. If the member function of the base class is declared virtual, the pointer can be used
to access the redefinition of the function in the derived class rather than the base class. This type of
behaviour is referred to as "dynamic binding". The correct implementation of the function is selected at
run-time.
When a virtual function is called by name and uses the dot operator, the reference is resolved at compile
time and is referred to as "static binding". Virtual functions are declared using the virtual keyword.
Once a function has been defined as virtual, it remains virtual down the inheritance tree from that point,
even if it's not declared virtual in sub-classes. However, it's considered good programming practice to
explicitly declare these functions virtual to aid clarity. If a derived class doesn't define the function, the
derived class inherits the function from the class it's being derived from. The redefinitions in the derived
classes of virtual functions must have identical arguments as those in the base class. ANSI C++ has
recently approved differing return types for virtual functions. Static members may not be be declared
virtual. Overloaded operators may be declared virtual, apart from the "new" and "delete" operators as
they become static, and static members can't be declared virtual.
Coordinate Example
The following example illustrates using virtual functions by declaring a virtual Display function in the
Coordinate class, and in a 3D coordinate class derived from the Coordinate class.
Coordinate Class
coordinate.h
#ifndef COORDINATE_H
#define COORDINATE_H
class Coordinate
protected:
int x;
int y;
public:
};
#endif
coordinate.cpp
#include <iostream.h>
#include "coordinate.h"
Coordinate::Coordinate(int a, int b)
Set(a, b);
x = a;
y = b;
cout << '[' << x << ", " << y << ']' << endl;
The 3D coordinate class is derived from the coordinate class. The 3D class (ThreeDCoord) is declared in
threedc.h, and defined in threedc.cpp.
threedc.h
#ifndef TDCOORD_H
#define TDCOORD_H
#include "coordinate.h"
protected:
int z;
public:
};
#endif
threedc.cpp
#include <iostream.h>
#include "threedc.h"
if (c > 0)
z = c;
else
z = 0;
x = a;
y = b;
z = c;
cout << '[' << x << ", " << y << ", " << z << ']' << endl;
usecoord.cpp
#include <iostream.h>
#include "coordinate.h"
#include "threedc.h"
int main()
c_ptr->Display();
c_ptr = &td;
c_ptr->Display();
return 0;
The following example illustrates the use of an array of pointers to display coordinates and de-allocate
memory for the coordinates. The class definitions are unchanged.
usecoord.cpp
#include <iostream.h>
#include "coordinate.h"
#include "threedc.h"
int main()
int counter;
Coordinate *c_ptr[4];
c_ptr[counter]->Display();
delete c_ptr[counter];
return 0;
Constructors may not be declared virtual, but destructors may be declared virtual to ensure an orderly de-
allocation of class objects. If the base class destructor is declared virtual, then all derived classes
automatically have virtual destructors. Destructors for non-virtual base classes are executed before the
destructors for virtual base classes. If memory is allocated in a class that contains one or more virtual
functions, then a virtual destructor should be used to ensure that the memory is deallocated correctly.
class someClass
public:
};
Abstracts Classes
You are here: Home > Tutorials > C++ > Abstract Classes
Sometimes it is necessary to declare a base class that has no useful function, when designing a class
hierarchy system. These types of classes cannot be instantiated and are referred to as abstract classes.
A class from which objects can be instantiated, is referred to as a concrete class and is the opposite of
an abstract class.
A class is made abstract by defining one or more of its virtual functions as pure. A pure virtual function is
one with an initialiser of = 0 in its declaration.
A class containing a pure virtual function cannot be instantiated. If a class is derived from a base class
containing a pure virtual function, and there is no definition for the pure virtual function in the derived
class, then the derived class is also an abstract class. Abstract classes cannot be used as a return type,
or used for type conversion.
http://192.168.16.242/cts/tutorials1/AllTutor/tutorial/cpp/abstractclasses.asp11/20/2006 3:33:48 PM
Juicy Studio: Polymorphism
Polymorphism
You are here: Home > Tutorials > C++ > Polymorphism
Polymorphism is the ability to define many different operations using the same name, and a common
interface to the programmer. The word polymorphism literally means many forms and is taken from the
Greek polus (meaning many) and morphe (meaning form). Polymorphism is implemented using virtual
functions. When a request is made through a base-class pointer to use a virtual function, the compiler
chooses the correct overridden function in the appropriate derived class. If a non-virtual member function
is called through a base class pointer to the derived class object, then the base class version of the
function is used. If client code has to make decisions about which object types to use, this usually
indicates poor class design.
A "Shape" class is an ideal candidate for an abstract class, as there are certain operations that cannot be
defined. For example, it is useless to try and devise an operation to return the area of a shape, as the
operation is performed differently depending on the shape. The calculation to determine the area of a
square is different to the calculation required to determine the area of a circle. The following example
uses an abstract class to define a shape.
The class shape contains pure virtual functions, so is abstract. The class is defined in shape.h.
shape.h
#ifndef SHAPE_H
#define SHAPE_H
class Shape
public:
};
#endif
The Circle class defines the pure virtual functions, Set, Area, and Display. The class is declared in circle.
h, and defined in circle.cpp.
circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream.h>
#include "shape.h"
private:
double radius;
public:
virtual void Display() const { cout << "Radius: " << radius << endl; }
};
#endif
circle.cpp
#include <iostream.h>
#include "circle.h"
void Circle::Set()
The Square class defines the pure virtual functions, Set, Area, and Display. The class is declared in
square.h, and defined in square.cpp.
square.h
#ifndef SQUARE_H
#define SQUARE_H
#include <iostream.h>
#include "shape.h"
private:
double length;
public:
virtual void Display() const { cout << "Length: " << length << endl; }
};
#endif
square.cpp
#include <iostream.h>
#include "square.h"
void Square::Set()
useclass.cpp
#include <iostream.h>
#include "square.h"
#include "circle.h"
int main()
Square s;
Circle c;
shapePtr->Set();
shapePtr->Display();
shapePtr = &c;
shapePtr->Set();
shapePtr->Display();
return 0;
The Standard Tempplate Library (STL) provides many standard templated container classes. Some of
the more popular container classes are, stack, queue, set, vector, list, and string.
To use any of these container classes, include their name and provide a namespace of std.
#include <somename>
All standard containers provide basic functionality, such as size, clear,and empty. Some containers have
container specific functions, such as push_front for list, and operator+ for string.
All standard conatiner classes provide operator=, copy constructor, destructor, and constructor(s).
Efficiency of Containers
Always use a container's member function over a generic function from the the STL library. For example,
use "s.find" to find an element in s, not the generic function "find" which is part of the algorithm library.
The reason is because the generic function "find" will potentially search every element of the container to
find X, whereas "s.find" uses the set container's built in find function which makes use of the set
container's storage property. Without going into more details, the generic find function will operate in O
(n), and the built in find function for the set container class will operate in lg(n). For those who dont
understand algorithm complexity, if a set has 4 billion distinct elements in it, the generic version of find
could take (in the worst case scanrio) 4 billion moves to find it, whereas the set container's version of find
will find the element in at most 32 moves.