c++ & visual c++

157
VISUAL C++ PROGRAMMING VC++ 1 [email protected] SUBJECT: Visual C++ CODE: 710/04/S05 AIMS OF THE SUBJECT 1. To review Object Oriented Program Design and relate it to specific programming languages. 2. To impart the skills to design applications in the VC++ development environment. 3. To impart the skills and knowledge to develop applications that use the fundamental features of C++, including Classes, Objects, Constructors, Inheritance, encapsulation, overloading etc.. DESIGN LENGTH THEORY 160 :Hours LABORATORY 100 :Hours TOTAL 260 :Hours SUBJECT OBJECTIVES The general objective of the units are stated below and the specific objectives of the topic areas are set out in the syllabus content. At the end of the course the student should be able to…. 1. ..design and implement Visual C++ applications using Object Oriented Programming design techniques. 2. ..create a Graphical User Interface in the Visual C++ programming environment. 3. ..add code to existing objects and add user defined classes and objects. 4. .. apply basic and more advanced features of Visual C++ in his/her programs, like objects, classes, inheritance, polymorphism etc.. 5. ..develop applications in Visual C++ that incorporate databases and access files.

Upload: makaha-rutendo

Post on 08-Jul-2015

737 views

Category:

Software


0 download

DESCRIPTION

PROGRAMMING USING C++ AND VISUAL C++

TRANSCRIPT

Page 1: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

1 [email protected]

SUBJECT: Visual C++ CODE: 710/04/S05

AIMS OF THE SUBJECT 1. To review Object Oriented Program Design and relate it to specific programming languages. 2. To impart the skills to design applications in the VC++ development environment. 3. To impart the skills and knowledge to develop applications that use the fundamental features of C++, including Classes, Objects, Constructors, Inheritance, encapsulation, overloading etc..

DESIGN LENGTH THEORY 160 :Hours LABORATORY 100 :Hours TOTAL 260 :Hours SUBJECT OBJECTIVES The general objective of the units are stated below and the specific objectives of the topic areas are set out in the syllabus content. At the end of the course the student should be able to…. 1. ..design and implement Visual C++ applications using Object Oriented Programming design

techniques. 2. ..create a Graphical User Interface in the Visual C++ programming environment. 3. ..add code to existing objects and add user defined classes and objects. 4. .. apply basic and more advanced features of Visual C++ in his/her programs, like objects,

classes, inheritance, polymorphism etc.. 5. ..develop applications in Visual C++ that incorporate databases and access files.

Page 2: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

2 [email protected]

Unit 1: Developing applications using the Visual C++ IDE (100HOURS) PRACTICAL This unit is for practical classes. It should complement the other units that are used for theory classes. At the end of the unit the student should be able to: 1. ..use the editor, the menus and the application wizard. 2. ..create projects. 3. ..understand and use controls: - General concepts

- Specific controls: e.g. combo box, labels, etc… 4. .. be able to create windows 5. .. understand what events and methods are 6. ..create a simple database application using DAO 7. ..design and implement applications using things like:

- Dialog Boxes - Mouse events, keyboard events, timers - Menu’s - Graphics

8. .. employ the above mentioned things in practical assignments

Page 3: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

3 [email protected]

Unit 2: Principal Concepts of OOP (10 HOURS) THEORY At the end of the unit the student should be able to.. 1. .. describe the evolution of software. 2. .. distinguish between procedure-oriented programming and object oriented programming. 3. ..know the Object Oriented Paradigm 3. ..understand basic concepts of Object Oriented Programming. 4. ..mention at least two Object Oriented Programming languages 5. ..mention several applications of Object Oriented Programming.

Distinguish between procedure-oriented programming and object

oriented programming. Procedure orientated programming is when a programmer creates functions and variables that

are separate parts for his or her program. They may work together but they are distinctly

separated. Object orientated programming is when a programmer takes a concept (an object)

and encapsulates all variables and functions into that concept so that the variables and

functions are distinctly connected. In C++, for example, these objects are called classes. C++

is an extension of the language C along with the capability of creating object classes.

Procedure Oriented Programming 1.Prime focus is on functions and procedures that operate on data

2.Large programs are divided into smaller program units called functions

3.Data and the functions that act upo it are treated as separate entities.

4. Data move freely around the systems from one function to another.

5. Program design follows “Top Down Approach”.

--------------------------------------…

Object Oriented Programming 1.Here more emphasis is laid on the data that is being operated and not the functions or

procedures

2.Programs are divided into what are called objects.

3. Both data and functions are treated together as an integral entity.

4. Data is hidden and cannot be accessed by external functions.

5. Program design follows “Bottom UP Approach”.

Page 4: C++ & VISUAL C++

The OOP Paradigm

Object oriented programming

overcome the problems that were found with using structured pro

While structured programming uses an approach which is top down, OOP uses an approach

which is bottom up. Traditionally, programming has placed an emphasis on logic and actions.

Object oriented programming has taken a completely diffe

emphasis on objects and information.

broken down into a number of units. These units are called objects. The foundation of OOP is

the fact that it will place an emphasis

Objects will be defined, and they will interact inside the system in a number of different

ways. There are a number of advantages to be found with usin

of these are simple maintenance, an advanced analysis of complicated programs, and

reusability. There are a number of programming languages that use OOP, and some of these

are Java, C++, and Ada. One concept that you will want

modeling. Before you can construct an object oriented system, you will first need to find the

objects within the system and determine the relationships they have. This process is called

data modeling. There are some other OO

A class is a unit that holds data and functions which will carry out operations on the data. A

class will be comprised of three access modifiers. These three modifiers are protected,

private, and public. A member that

designated as private cannot be accessed by objects that exist outside the system. In addition

to this, it cannot be inherited. While a member who is protected can be inherited, they cannot

be accessed by objects which reside outside of the class hierarchy. Another term that you will

hear about often in OOP is objects.

An object is a state of class. It can receive and send messages to other objects, and it can

handle data. The objects which exist w

and will behave in the same manner. There are two things that are found with all objects that

exist in the real world. These two things are behaviors and states. While behaviors and states

are found in real world objects, they can also be found in software objects as well. Another

OOP concept that you will need to know is a method. A method is a process that is used to

handle an object. A method can be public, protected, or private. The visibility of th

will determine how much of it can be seen by outside objects.

Inheritance is an aspect of OOP that allows subclasses to inherit the traits and characteristics

of its superclass. The subclass will inherit all members except those that designated

private. The subclass may have a large number classes from multiple bases, and this concept

is called Multiple Inheritance. It is possible for a subclass to use the behavior of the members

it has inherited, and it can also add new members as well.

that inheritance has, and these are the implementation of abstract data and reusability.

Encapsulation is another important concept that you will need to know. In a nutshell,

encapsulation is responsible for shielding t

only reveal the functional information. However, the implementation will be hidden.

VISUAL C++ PROGRAMMING

[email protected]

programming is a concept that was created because of the need to

overcome the problems that were found with using structured programming techniques.

While structured programming uses an approach which is top down, OOP uses an approach

which is bottom up. Traditionally, programming has placed an emphasis on logic and actions.

Object oriented programming has taken a completely different direction, and will place an

emphasis on objects and information. With object oriented programming, a problem will be

broken down into a number of units. These units are called objects. The foundation of OOP is

the fact that it will place an emphasis on objects and classes .

will be defined, and they will interact inside the system in a number of different

ways. There are a number of advantages to be found with using the OOP paradigm, and some

of these are simple maintenance, an advanced analysis of complicated programs, and

reusability. There are a number of programming languages that use OOP, and some of these

are Java, C++, and Ada. One concept that you will want to become familiar with is data

modeling. Before you can construct an object oriented system, you will first need to find the

objects within the system and determine the relationships they have. This process is called

data modeling. There are some other OOP terms that you will want to know.

is a unit that holds data and functions which will carry out operations on the data. A

class will be comprised of three access modifiers. These three modifiers are protected,

private, and public. A member that is public can be accessed and inherited. A member that is

designated as private cannot be accessed by objects that exist outside the system. In addition

to this, it cannot be inherited. While a member who is protected can be inherited, they cannot

sed by objects which reside outside of the class hierarchy. Another term that you will

hear about often in OOP is objects.

is a state of class. It can receive and send messages to other objects, and it can

handle data. The objects which exist within software are often based off real world objects,

and will behave in the same manner. There are two things that are found with all objects that

exist in the real world. These two things are behaviors and states. While behaviors and states

real world objects, they can also be found in software objects as well. Another

OOP concept that you will need to know is a method. A method is a process that is used to

handle an object. A method can be public, protected, or private. The visibility of th

will determine how much of it can be seen by outside objects.

is an aspect of OOP that allows subclasses to inherit the traits and characteristics

of its superclass. The subclass will inherit all members except those that designated

private. The subclass may have a large number classes from multiple bases, and this concept

is called Multiple Inheritance. It is possible for a subclass to use the behavior of the members

it has inherited, and it can also add new members as well. There are two powerful advantages

that inheritance has, and these are the implementation of abstract data and reusability.

is another important concept that you will need to know. In a nutshell,

encapsulation is responsible for shielding the data within a class from outside objects. It will

only reveal the functional information. However, the implementation will be hidden.

VISUAL C++ PROGRAMMING VC++

4

is a concept that was created because of the need to

gramming techniques.

While structured programming uses an approach which is top down, OOP uses an approach

which is bottom up. Traditionally, programming has placed an emphasis on logic and actions.

rent direction, and will place an

With object oriented programming, a problem will be

broken down into a number of units. These units are called objects. The foundation of OOP is

will be defined, and they will interact inside the system in a number of different

g the OOP paradigm, and some

of these are simple maintenance, an advanced analysis of complicated programs, and

reusability. There are a number of programming languages that use OOP, and some of these

to become familiar with is data

modeling. Before you can construct an object oriented system, you will first need to find the

objects within the system and determine the relationships they have. This process is called

P terms that you will want to know.

is a unit that holds data and functions which will carry out operations on the data. A

class will be comprised of three access modifiers. These three modifiers are protected,

is public can be accessed and inherited. A member that is

designated as private cannot be accessed by objects that exist outside the system. In addition

to this, it cannot be inherited. While a member who is protected can be inherited, they cannot

sed by objects which reside outside of the class hierarchy. Another term that you will

is a state of class. It can receive and send messages to other objects, and it can

ithin software are often based off real world objects,

and will behave in the same manner. There are two things that are found with all objects that

exist in the real world. These two things are behaviors and states. While behaviors and states

real world objects, they can also be found in software objects as well. Another

OOP concept that you will need to know is a method. A method is a process that is used to

handle an object. A method can be public, protected, or private. The visibility of the member

is an aspect of OOP that allows subclasses to inherit the traits and characteristics

of its superclass. The subclass will inherit all members except those that designated as being

private. The subclass may have a large number classes from multiple bases, and this concept

is called Multiple Inheritance. It is possible for a subclass to use the behavior of the members

There are two powerful advantages

that inheritance has, and these are the implementation of abstract data and reusability.

is another important concept that you will need to know. In a nutshell,

he data within a class from outside objects. It will

only reveal the functional information. However, the implementation will be hidden.

Page 5: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

5 [email protected]

Encapsulation is a concept which promotes modularity, and it is also crucial for hiding

information.

Abstraction is an important concept as well. It allows an application to process objects on a

general level. It is not connected to the instance of an object. It is excellent for locating

patterns that may have a number of different variations. Abstractions are useful because they

can create a common identification that can be found within all their subclasses.

This article serves to demonstrate some of the general concepts of OOP. Object oriented

programming is a paradigm that has created a revolution within the field of computer

programming. If it is used to design programs properly, they will be efficient and easy to

expand and maintain.

Polymorphism Polymorphism is the ability to apply a standard interface to an object. For example, just about

every electronic device has an on/off switch which performs the same task. The interface to

us is simple and straight forward. What happens inside the electronic device will vary greatly

between devices.

What this means to a C++ programmer is that objects have functions assigned to them, and

similar objects (or derived objects) will implement the same function name to accomplish the

same task, while the mechanics of how it is done may be greatly different.

For example, imaging two objects, one handles input from a keyboard, and the other handles

input from a modem. Both objects implement a function called GetLine. This GetLine

function does the same job from the application viewpoint, it gets a line from an input device.

Our application doesn't have to care if the user is at the keyboard, or across the country via

modem. Chances are that our keyboard object and modem object are both derived from a

standard 'Input' object or base object. All similar objects derived from the Input object would

have to provide the GetLine function.

Page 6: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

6 [email protected]

Unit 3: Visual C++ basics: Data types, expressions, control structur (30 HOURS) THEORY At the end of the unit the student should be able to: 1. ..describe what Visual C++ is. 2. ..give examples of applications of C++ 3. ..write a simple Visual C++ program 4. ..describe the structure of a Visual C++ program 5. ..use pre-processor directives 6. ..know how to compile and link a source program 7. ..describe what tokens, keywords and identifiers are 8. ..list the basic data types and their characteristics 9. ..create user defined data types and derived data types 10. ..know about compatibility of data types 11. ..be able to declare variables 12. ..employ dynamic initialisation of variables 13. ..know what reference variables are 14. ..list the possible operations in Visual C++ 15. ..know the following about operators:

- Scope Resolution Operator - Member Differencing Operator - Memory Management Operator - Manipulators - operator overloading - operator precedence - Type Cast Operator

16. ..know expressions and implicit conversions 17. ..know the control structures of C++ e.g. while, for, if etc..

Your first C++ program You now know almost enough of the basics to create and compile a program. The program will use the Standard C++ iostream classes. These read from and write to files and “standard” input and output (which normally comes from and goes to the console, but may be redirected to files or devices). In this very simple program, a stream object will be used to print a message on the screen.

Using the iostreams class

To declare the functions and external data in the iostreams class, include the header file with the statement #include <iostream>

Page 7: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

7 [email protected]

The first program uses the concept of standard output, which means “a general-purpose place to send output.” You will see other examples using standard output in different ways, but here it will just go to the console. The iostream package automatically defines a variable (an object) called cout that accepts all data bound for standard output. To send data to standard output, you use the operator <<. C programmers know this operator as the “bitwise left shift,” which will be described in the next chapter. Suffice it to say that a bitwise left shift has nothing to do with output. However, C++ allows operators to be overloaded. When you overload an operator, you give it a new meaning when that operator is used with an object of a particular type. With iostream objects, the operator << means “send to.” For example: cout << "howdy!"; sends the string “howdy!” to the object called cout (which is short for “console output”). That’s enough operator overloading to get you started. Chapter XX covers operator overloading in detail. Namespaces As mentioned in the previous chapter, one of the problems encountered in the C language is that you “run out of names” for functions and identifiers when your programs reach a certain size. Of course, you don’t really run out of names – however, it becomes harder to think of new ones after awhile. More importantly, when a program reaches a certain size it’s typically broken up into pieces, each of which is built and maintained by a different person or group. Since C effectively has a single arena where all the identifier and function names live, this means that all the developers must be careful not to accidentally use the same names in situations where they can conflict. This rapidly becomes tedious, time-wasting and, ultimately, expensive. Standard C++ has a mechanism to prevent this collison: the namespace keyword. Each set of C++ definitions in a library or program is “wrapped” in a namespace, and if some other definition has an identical name, but is in a different namespace, then there is no collision. Namespaces are a convenient and helpful tool, but their presence means you must be aware of them before you can write any programs at all. If you simply include a header file and use some functions or objects from that header, you’ll probably get strange-sounding errors when you try to compile the program, to the effect that the compiler cannot find any of the declarations for the items that you just included in the header file! After you see this message a few times you’ll become familiar with its meaning (which is: “you included the header file but all the declarations are within a namespace and you didn’t tell the compiler that you wanted to use the declarations in that namespace”). There’s a keyword that allows you to say “I want to use the declarations and/or definitions in this namespace.” This keyword, appropriately enough, is using. All of the Standard C++ libraries are wrapped in a single namespace, which is std (for “standard”). As this book uses the standard libraries almost exclusively, you’ll see the following using directive in almost every program: using namespace std; This means that you want to expose all the elements from the namespace called std. After this statement, you don’t have to worry that your particular library component is inside a namespace, since the using directive makes that namespace available throughout the file where the using directive was written.

Page 8: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

8 [email protected]

Exposing all the elements from a namespace after someone has gone to the trouble to hide them may seem a bit counterproductive, and in fact you should be careful about thoughtlessly doing this (as you’ll learn later in the book). However, the using directive only exposes those names for the current file, so it is not quite so drastic as it first sounds (but think twice about doing it in a header file – that is reckless). There’s a relationship between namespaces and the way header files are included. Before the current header file inclusion style of <iostream> (that is, no trailing ‘ .h’) was standardized, the typical way to include a header file was with the ‘ .h’, such as <iostream.h>. At that time, namespaces were not part of the language, either. So to provide backwards compatibility with existing code, if you say #include <iostream.h> It means #include <iostream> using namespace std; However, in this book the standard include format will be used (without the ‘ .h’) and so the using directive must be explicit. For now, that’s all you need to know about namespaces, but in Chapter XX the subject is covered much more thoroughly. Fundamentals of program structure A C or C++ program is a collection of variables, function definitions and function calls. When the program starts, it executes initialization code and calls a special function, “ main( ).” You put the primary code for the program here. As mentioned earlier, a function definition consists of a return type (which must be specified in C++), a function name, an argument list in parentheses, and the function code contained in braces. Here is a sample function definition: int function() { // Function code here (this is a comment) } The above function has an empty argument list, and a body that contains only a comment. There can be many sets of braces within a function definition, but there must always be at least one set surrounding the function body. Since main( ) is a function, it must follow these rules. In C++, main( ) always has return type of int. C and C++ are free form languages. With few exceptions, the compiler ignores newlines and white space, so it must have some way to determine the end of a statement. Statements are delimited by semicolons. C comments start with /* and end with */. They can include newlines. C++ uses C-style comments and has an additional type of comment: //. The // starts a comment that terminates with a newline. It is more convenient than /* */ for one-line comments, and is used extensively in this book.

Page 9: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

9 [email protected]

"Hello, world!"

And now, finally, the first program: //: C02:Hello.cpp // Saying Hello with C++ #include <iostream> // Stream declarations using namespace std; int main() { cout << "Hello, World! I am " << 8 << " Today!" << endl; } ///:~ The cout object is handed a series of arguments via the ‘ <<’ operators. It prints out these arguments in left-to-right order. The special iostream function endl outputs the line and a newline. With iostreams, you can string together a series of arguments like this, which makes the class easy to use. In C, text inside double quotes is traditionally called a “string.” However, the Standard C++ library has a powerful class called string for manipulating text, and so I shall use the more precise term character array for text inside double quotes. The compiler creates storage for character arrays and stores the ASCII equivalent for each character in this storage. The compiler automatically terminates this array of characters with an extra piece of storage containing the value 0, to indicate the end of the character array. Inside a character array, you can insert special characters by using escape sequences. These consist of a backslash ( \) followed by a special code. For example \n means newline. Your compiler manual or local C guide gives a complete set of escape sequences; others include \t (tab), \\ (backslash) and \b (backspace). Notice that the entire statement terminates with a semicolon. Character array arguments and constant numbers are mixed together in the above cout statement. Because the operator << is overloaded with a variety of meanings when used with cout, you can send cout a variety of different arguments, and it will “figure out what to do with the message.” Throughout this book you’ll notice that the first line of each file will be a comment that starts with the characters that start a comment (typically //), followed by a colon. // my first program in C++ #include <iostream> using namespace std; int main () { cout << "Hello World!"; return 0; } // my first program in C++

Page 10: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

10 [email protected]

This is a comment line. All lines beginning with two slash signs (//) are considered comments and do not have any effect on the behavior of the program. The programmer can use them to include short explanations or observations within the source code itself. In this case, the line is a brief description of what our program is.

#include <iostream>

Lines beginning with a pound sign (#) are directives for the preprocessor. They are not regular code lines with expressions but indications for the compiler's preprocessor. In this case the directive #include <iostream> tells the preprocessor to include the iostream standard file. This specific file (iostream) includes the declarations of the basic standard input-output library in C++, and it is included because its functionality is going to be used later in the program.

using namespace std;

All the elements of the standard C++ library are declared within what is called a namespace, the namespace with the name std. So in order to access its functionality we declare with this expression that we will be using these entities. This line is very frequent in C++ programs that use the standard library, and in fact it will be included in most of the source codes included in these tutorials.

int main ()

This line corresponds to the beginning of the definition of the main function. The main function is the point by where all C++ programs start their execution, independently of its location within the source code. It does not matter whether there are other functions with other names defined before of after it - the instructions contained within this function's definition will always be the first ones to be executed in any C++ program. For that same reason, it is essential that all C++ programs have a main function.

The word main is followed in the code by a pair of parentheses (()). That is because it is a function declaration: In C++, what differentiates a function declaration from other types of expressions are these parentheses that follow its name. Optionally, these parentheses may enclose a list of parameters within them.

Right after these parentheses we can find the body of the main function enclosed in braces ({}). What is contained within these braces is what the function does when it is executed.

cout << "Hello World";

This line is a C++ statement. A statement is a simple or compound expression that can actually produce some effect. In fact, this statement performs the only action that generates a visible effect in our first program.

cout represents the standard output stream in C++, and the meaning of the entire statement is to insert a sequence of characters (in this case the Hello World sequence of characters) into the standard output stream (which usually is the screen).

cout is declared in the iostream standard file within the std namespace, so that's why we needed to include that specific file and to declare that we were going to use this specific namespace earlier in our code.

Page 11: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

11 [email protected]

Notice that the statement ends with a semicolon character (;). This character is used to mark the end of the statement and in fact it must be included at the end of all expression statements in all C++ programs (one of the most common syntax errors is indeed to forget to include some semicolon after a statement).

return 0;

The return statement causes the main function to finish. return may be followed by a return code (in our example is followed by the return code 0). A return code of 0 for the main function is generally interpreted as the program worked as expected without any errors during its execution. This is the most usual way to end a C++ program.

You may have noticed that not all the lines of this program perform actions when the code is executed. There were lines containing only comments (those beginning by //). There were lines with directives for the compiler's preprocessor (those beginning by #). Then there were lines that began the declaration of a function (in this case, the main function) and, finally lines with statements (like the insertion into cout), which were all included within the block delimited by the braces ({}) of the main function.

Preprocessor directives (those that begin by #) are out of this general rule since they are not statements. They are lines read and discarded by the preprocessor and do not produce any code by themselves. Preprocessor directives must be specified in their own line and do not have to end with a semicolon (;).

Comments

Comments are parts of the source code disregarded by the compiler. They simply do nothing. Their purpose is only to allow the programmer to insert notes or descriptions embedded within the source code.

C++ supports two ways to insert comments:

// line comment /* block comment */

The first of them, known as line comment, discards everything from where the pair of slash signs (//) is found up to the end of that same line. The second one, known as block comment, discards everything between the /* characters and the first appearance of the */ characters, with the possibility of including more than one line.

Page 12: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

12 [email protected]

If you include comments within the source code of your programs without using the comment characters combinations //, /* or */, the compiler will take them as if they were C++ expressions, most likely causing one or several error messages when you compile it.

Variables. Data Types.

Each variable needs an identifier that distinguishes it from the others, for example, in the previous code the variable identifiers were a, b and result, but we could have called the variables any names we wanted to invent, as long as they were valid identifiers.

Identifiers

A valid identifier is a sequence of one or more letters, digits or underline characters (_). Neither spaces nor punctuation marks or symbols can be part of an identifier. Only letters, digits and underline characters are valid. In addition, variable identifiers always have to begin with a letter. They can also begin with an underline character (_ ), but this is usually reserved for compiler specific keywords or external identifiers. In no case they can begin with a digit.

Another rule that you have to consider when inventing your own identifiers is that they cannot match any keyword of the C++ language or your compiler's specific ones since they could be confused with these. The standard reserved keywords are:

asm, auto, bool, break, case, catch, char, class, const, const_cast, continue, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, operator, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_cast, struct, switch, template, this, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while

Additionally, alternative representations for some operators cannot be used as identifiers since they are reserved words under some circumstances:

and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq

Your compiler may also include some additional specific reserved keywords. Very important: The C++ language is a "case sensitive" language. That means that an identifier

Page 13: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

13 [email protected]

written in capital letters is not equivalent to another one with the same name but written in small letters. Thus, for example, the RESULT variable is not the same as the result variable or the Result variable. These are three different variable identifiers.

Fundamental data types

When programming, we store the variables in our computer's memory, but the computer has to know what we want to store in them, since it is not going to occupy the same amount of memory to store a simple number than to store a single letter or a large number, and they are not going to be interpreted the same way.

The memory in our computers is organized in bytes. A byte is the minimum amount of memory that we can manage in C++. A byte can store a relatively small amount of data: one single character or a small integer (generally an integer between 0 and 255). In addition, the computer can manipulate more complex data types that come from grouping several bytes, such as long numbers or non-integer numbers.

Next you have a summary of the basic fundamental data types in C++, as well as the range of values that can be represented with each one:

Name Description Size* Range*

char Character or small integer. 1byte signed: -128 to 127 unsigned: 0 to 255

short int (short)

Short Integer. 2bytes signed: -32768 to 32767 unsigned: 0 to 65535

int Integer. 4bytes signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295

long int (long)

Long integer. 4bytes signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295

bool Boolean value. It can take one of two values: true or false.

1byte true or false

float Floating point number. 4bytes 3.4e +/- 38 (7 digits) double Double precision floating point number. 8bytes 1.7e +/- 308 (15 digits) long double Long double precision floating point number. 8bytes 1.7e +/- 308 (15 digits) wchar_t Wide character. 2bytes 1 wide character

* The values of the columns Size and Range depend on the architecture of the system where the program is compiled and executed. The values shown above are those found on most 32bit systems. But for other systems, the general specification is that int has the natural size suggested by the system architecture (one word) and the four integer types char, short, int and long must

Page 14: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

14 [email protected]

each one be at least as large as the one preceding it. The same applies to the floating point types float, double and long double, where each one must provide at least as much precision as the preceding one.

Introducing strings While a character array can be fairly useful, it is quite limited. It’s simply a group of characters in memory, but if you want to do anything with it you must manage all the little details. For example, the size of a quoted character array is fixed at compile time. If you have a character array and you want to add some more characters to it, you’ll need to understand quite a lot (inluding dynamic memory management, character array copying and concatenation) before you can get your wish. This is exactly the kind of thing we’d like to have an object do for us. The Standard C++ string class is designed to take care of (and hide) all the low-level manipulations of character arrays that were previously required of the C++ programmer. These manipulations have been a constant source of time-wasting and errors since the inception of the C language. So, although an entire chapter is devoted to the string class later in the book, the string is so important and it makes life so much easier that it will be introduced here and used in much of the early part of the book. To use strings you include the C++ header file <string>. The string class is in the namespace std so a using directive is necessary. Because of operator overloading, the syntax for using strings is quite intuitive: //: C02:HelloStrings.cpp // The basics of the Standard C++ string class #include <string> #include <iostream> using namespace std; int main() { string s1, s2; // Empty strings string s3 = "Hello, World."; // Initialized string s4("I am"); // Also initialized s2 = "Today"; // Assigning to a string s1 = s3 + " " + s4; // Combining strings s1 += " 8 "; // Appending to a string cout << s1 + s2 + "!" << endl; } ///:~ The first two strings, s1 and s2, start out empty, while s3 and s4 show two equivalent ways to initialize string objects from character arrays (you can as easily initialize string objects from other string objects). You can assign to any string object using ‘ =’. This replaces the previous contents of the string with whatever is on the right-hand side, and you don’t have to worry about what happens to the previous contents – that’s handled automatically for you. To combine strings you simply use the ‘ +’ operator, which also allows you to combine character arrays with strings. If you want to append either a string or a character array to another string, you can use the operator ‘ +=’. Finally, note that iostreams already know what to do with strings, so you can just send a string (or an expression that produces a string, which happens with s1 + s2 + "!" ) directly to cout in order to print it.

Page 15: C++ & VISUAL C++

Variables that can store non-numerical values that are longer than one single character are known as strings. The C++ language library provides support for strings through the standard not a fundamental type, but it behaves in a similar way as fundamental types do in its most basic usage. A first difference with fundamental data types is that in order to declare and use objects (variables) of this type we need to include an additand have access to the std namespace (which we already had in all our previous programs thanks to the using namespace statement). // my first string #include <iostream> #include <string> using namespace std; int main () { string mystring = "This is a string" cout << mystring; return 0;

}

Scope of variables All the variables that we intend to use in a program must have been declared with its type specifier in an earlier point in the code, like we did ibody of the function main when we declared that

A variable can be either of global or local scope. A global variable is a variable declared in the main body of the source code, the body of a function or a block.

VISUAL C++ PROGRAMMING

[email protected]

numerical values that are longer than one single character are

The C++ language library provides support for strings through the standard stringnot a fundamental type, but it behaves in a similar way as fundamental types do in its most basic

A first difference with fundamental data types is that in order to declare and use objects (variables) of this type we need to include an additional header file in our source code:

namespace (which we already had in all our previous programs thanks statement).

"This is a string";

All the variables that we intend to use in a program must have been declared with its type specifier in an earlier point in the code, like we did in the previous code at the beginning of the body of the function main when we declared that a, b, and result were of type

A variable can be either of global or local scope. A global variable is a variable declared in the outside all functions, while a local variable is one declared within

the body of a function or a block.

VISUAL C++ PROGRAMMING VC++

15

numerical values that are longer than one single character are

string class. This is not a fundamental type, but it behaves in a similar way as fundamental types do in its most basic

A first difference with fundamental data types is that in order to declare and use objects ional header file in our source code: <string>

namespace (which we already had in all our previous programs thanks

All the variables that we intend to use in a program must have been declared with its type n the previous code at the beginning of the

were of type int.

A variable can be either of global or local scope. A global variable is a variable declared in the outside all functions, while a local variable is one declared within

Page 16: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

16 [email protected]

Global variables can be referred from anywhere in the code, even inside functions, whenever it is after its declaration.

The scope of local variables is limited to the block enclosed in braces ({}) where they are declared. For example, if they are declared at the beginning of the body of a function (like in function main) their scope is between its declaration point and the end of that function. In the example above, this means that if another function existed in addition to main, the local variables declared in main could not be accessed from the other function and vice versa.

Initialization of variables

When declaring a regular local variable, its value is by default undetermined. But you may want a variable to store a concrete value at the same moment that it is declared. In order to do that, you can initialize the variable. There are two ways to do this in C++:

The first one, known as c-like, is done by appending an equal sign followed by the value to which the variable will be initialized:

type identifier = initial_value ;

For example, if we want to declare an int variable called a initialized with a value of 0 at the moment in which it is declared, we could write:

int a = 0;

The other way to initialize variables, known as constructor initialization, is done by enclosing the initial value between parentheses (()):

type identifier (initial_value) ;

For example:

int a (0);

Both ways of initializing variables are valid and equivalent in C++.

// initialization of variables #include <iostream>

Page 17: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

17 [email protected]

using namespace std; int main () { int a=5; // initial value = 5 int b(2); // initial value = 2 int result; // initial value undetermined a = a + 3; result = a - b; cout << result; return 0; } 6 Specifying storage allocation When creating a variable, you have a number of options to specify the lifetime of the variable, how the storage is allocated for that variable, and how the variable is treated by the compiler.

Global variables

Global variables are defined outside all function bodies and are available to all parts of the program (even code in other files). Global variables are unaffected by scopes and are always available (i.e., the lifetime of a global variable lasts until the program ends). If the existence of a global variable in one file is declared using the extern keyword in another file, the data is available for use by the second file. Here’s an example of the use of global variables: //: C03:Global.cpp //{L} Global2 // Demonstration of global variables #include <iostream> using namespace std; int globe; void func(); int main() { globe = 12; cout << globe << endl; func(); // Modifies globe cout << globe << endl; } ///:~ Here’s a file that accesses globe as an extern: //: C03:Global2.cpp {O} // Accessing external global variables extern int globe; // (The linker resolves the reference) void func() { globe = 47; } ///:~

Page 18: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

18 [email protected]

Storage for the variable globe is created by the definition in Global.cpp, and that same variable is accessed by the code in Global2.cpp. Since the code in Global2.cpp is compiled separately from the code in Global.cpp, the compiler must be informed that the variable exists elsewhere by the declaration extern int globe; When you run the program, you’ll see that the call to func( ) does indeed affect the single global instance of globe. In Global.cpp, you can see the special comment tag (which is my own design): //{L} Global2 This says that to create the final program, the object file with the name Global2 must be linked in (there is no extension because the extension names of object files differ from one system to the next). In Global2.cpp, the first line has another special comment tag {O} which says “don’t try to create an executable out of this file, it’s being compiled so that it can be linked into some other executable.” The ExtractCode.cpp program at the end of this book reads these tags and creates the appropriate makefile so everything compiles properly (you’ll learn about makefiles at the end of this chapter).

Local variables

Local variables occur within a scope; they are “local” to a function. They are often called automatic variables because they automatically come into being when the scope is entered, and automatically go away when the scope closes. The keyword auto makes this explicit, but local variables default to auto so it is never necessary to declare something as an auto. Register variables A register variable is a type of local variable. The register keyword tells the compiler “make accesses to this variable as fast as possible.” Increasing the access speed is implementation dependent but, as the name suggests, it is often done by placing the variable in a register. There is no guarantee that the variable will be placed in a register or even that the access speed will increase. It is a hint to the compiler. There are restrictions to the use of register variables. You cannot take or compute the address of a register variable. A register variable can only be declared within a block (you cannot have global or static register variables). You can, however, use a register variable as a formal argument in a function (i.e., in the argument list). Generally, you shouldn’t try to second-guess the compiler’s optimizer, since it will probably do a better job than you can. Thus, the register keyword is best avoided.

Static

The static keyword has several distinct meanings. Normally, variables defined local to a function disappear at the end of the function scope. When you call the function again, storage for the variables is created anew and the values are re-initialized. If you want a value to be extant

Page 19: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

19 [email protected]

throughout the life of a program, you can define a function’s local variable to be static and give it an initial value. The initialization is only performed the first time the function is called, and the data retains its value between function calls. This way, a function can “remember” some piece of information between function calls. You may wonder why a global variable isn’t used instead. The beauty of a static variable is that it is unavailable outside the scope of the function, so it can’t be inadvertently changed. This localizes errors. Here’s an example of the use of static variables: //: C03:Static.cpp // Using a static variable in a function #include <iostream> using namespace std; void func() { static int i = 0; cout << "i = " << ++i << endl; } int main() { for(int x = 0; x < 10; x++) func(); } ///:~ Each time func( ) is called in the for loop, it prints a different value. If the keyword static is not used, the value printed will always be ‘1’. The second meaning of static is related to the first in the “unavailable outside a certain scope” sense. When static is applied to a function name or to a variable that is outside of all functions, it means “this name is unavailable outside of this file.” The function name or variable is local to the file; we say it has file scope. As a demonstration, compiling and linking the following two files will cause a linker error: //: C03:FileStatic.cpp // File scope demonstration. Compiling and // linking this file with FileStatic2.cpp // will cause a linker error // File scope means only available in this file: static int fs; int main() { fs = 1; } ///:~ Even though the variable fs is claimed to exist as an extern in the following file, the linker won’t find it because it has been declared static in FileStatic.cpp. //: C03:FileStatic2.cpp {O} // Trying to reference fs extern int fs;

Page 20: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

20 [email protected]

void func() { fs = 100; } ///:~ The static specifier may also be used inside a class. This explanation will be delayed until you learn to create classes, later in the book.

Extern

The extern keyword has already been briefly described and demonstrated. It tells the compiler that a variable or a function exists, even if the compiler hasn’t yet seen it in the file currently being compiled. This variable or function may be defined in another file or further down in the current file. As an example of the latter: //: C03:Forward.cpp // Forward function & data declarations #include <iostream> using namespace std; // This is not actually external, but the // compiler must be told it exists somewhere: extern int i; extern void func(); int main() { i = 0; func(); } int i; // The data definition void func() { i++; cout << i; } ///:~ When the compiler encounters the declaration ‘ extern int i ’ it knows that the definition for i must exist somewhere as a global variable. When the compiler reaches the definition of i, no other declaration is visible so it knows it has found the same i declared earlier in the file. If you were to define i as static, you would be telling the compiler that i is defined globally (via the extern), but it also has file scope (via the static), so the compiler will generate an error. Linkage To understand the behavior of C and C++ programs, you need to know about linkage. In an executing program, an identifier is represented by storage in memory that holds a variable or a compiled function body. Linkage describes this storage it is seen by the linker. There are two types of linkage: internal linkage and external linkage. Internal linkage means that storage is created to represent the identifier only for the file being compiled. Other files may use the same identifier name with internal linkage, or for a global variable, and no conflicts will be found by the linker – separate storage is created for each identifier. Internal linkage is specified by the keyword static in C and C++.

Page 21: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

21 [email protected]

External linkage means that a single piece of storage is created to represent the identifier for all files being compiled. The storage is created once, and the linker must resolve all other references to that storage. Global variables and function names have external linkage. These are accessed from other files by declaring them with the keyword extern. Variables defined outside all functions (with the exception of const in C++) and function definitions default to external linkage. You can specifically force them to have internal linkage using the static keyword. You can explicitly state that an identifier has external linkage by defining it with the extern keyword. Defining a variable or function with extern is not necessary in C, but it is sometimes necessary for const in C++. Automatic (local) variables exist only temporarily, on the stack, while a function is being called. The linker doesn’t know about automatic variables, and they have no linkage.

Constants

In old (pre-Standard) C, if you wanted to make a constant, you had to use the preprocessor: #define PI 3.14159 Everywhere you used PI, the value 3.14159 was substituted by the preprocessor (you can still use this method in C and C++). When you use the preprocessor to create constants, you place control of those constants outside the scope of the compiler. No type checking is performed on the name PI and you can’t take the address of PI (so you can’t pass a pointer or a reference to PI). PI cannot be a variable of a user-defined type. The meaning of PI lasts from the point it is defined to the end of the file; the preprocessor doesn’t recognize scoping. C++ introduces the concept of a named constant that is just like a variable, except its value cannot be changed. The modifier const tells the compiler that a name represents a constant. Any data type, built-in or user-defined, may be defined as const. If you define something as const and then attempt to modify it, the compiler will generate an error. You must specify the type of a const, like this: const int x = 10; In Standard C and C++, you can use a named constant in an argument list, even if the argument it fills is a pointer or a reference (i.e., you can take the address of a const). A const has a scope, just like a regular variable, so you can “hide” a const inside a function and be sure that the name will not affect the rest of the program. The const was taken from C++ and incorporated into Standard C, albeit quite differently. In C, the compiler treats a const just like a variable that has a special tag attached that says “don’t change me.” When you define a const in C, the compiler creates storage for it, so if you define more than one const with the same name in two different files (or put the definition in a header file), the linker will generate error messages about conflicts. The intended use of const in C is quite different from its intended use in C++ (in short, it’s nicer in C++).

Page 22: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

22 [email protected]

Constant values In C++, a const must always have an initialization value (in C, this is not true). Constant values for built-in types are expressed as decimal, octal, hexadecimal, or floating-point numbers (sadly, binary numbers were not considered important), or as characters. In the absence of any other clues, the compiler assumes a constant value is a decimal number. The numbers 47, 0 and 1101 are all treated as decimal numbers. A constant value with a leading 0 is treated as an octal number (base 8). Base 8 numbers can only contain digits 0-7; the compiler flags other digits as an error. A legitimate octal number is 017 (15 in base 10). A constant value with a leading 0x is treated as a hexadecimal number (base 16). Base 16 numbers contain the digits 0-9 and a-f or A-F. A legitimate hexadecimal number is 0x1fe (510 in base 10). Floating point numbers can contain decimal points and exponential powers (represented by e, which means “10 to the power”). Both the decimal point and the e are optional. If you assign a constant to a floating-point variable, the compiler will take the constant value and convert it to a floating-point number (this process is one form of what’s called implicit type conversion). However, it is a good idea to use either a decimal point or an e to remind the reader you are using a floating-point number; some older compilers also need the hint. Legitimate floating-point constant values are: 1e4, 1.0001, 47.0, 0.0 and -1.159e-77. You can add suffixes to force the type of floating-point number: f or F forces a float, L or l forces a long double, otherwise the number will be a double. Character constants are characters surrounded by single quotes, as: ‘ A’, ‘ 0’, ‘ ‘. Notice there is a big difference between the character ‘ 0’ (ASCII 96) and the value 0. Special characters are represented with the “backslash escape”: ‘ \n’ (newline), ‘ \t’ (tab), ‘ \\’ (backslash), ‘ \r’ (carriage return), ‘ \"’ (double quotes), ‘ \'’ (single quote), etc. You can also express char constants in octal: ‘ \17’ or hexadecimal: ‘ \xff’.

Volatile

Whereas the qualifier const tells the compiler “this never changes” (which allows the compiler to perform extra optimizations) the qualifier volatile tells the compiler “you never know when this will change,” and prevents the compiler from performing any optimizations. Use this keyword when you read some value outside the control of your code, such as a register in a piece of communication hardware. A volatile variable is always read whenever its value is required, even if it was just read the line before. A special case of some storage being “outside the control of your code” is in a multithreaded program. If you’re watching a particular flag that is modified by another thread or process, that flag should be volatile so the compiler doesn’t make the assumption that it can optimize away multiple reads of the flag.

Page 23: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

23 [email protected]

Constants

Constants are expressions with a fixed value.

Literals

Literals are used to express particular values within the source code of a program. We have already used these previously to give concrete values to variables or to express messages we wanted our programs to print out, for example, when we wrote:

a = 5;

the 5 in this piece of code was a literal constant.

Literal constants can be divided in Integer Numerals, Floating-Point Numerals, Characters, Strings and Boolean Values.

Integer Numerals 1776 707 -273

They are numerical constants that identify integer decimal values. Notice that to express a numerical constant we do not have to write quotes (") nor any special character. There is no doubt that it is a constant: whenever we write 1776 in a program, we will be referring to the value 1776.

In addition to decimal numbers (those that all of us are used to use every day) C++ allows the use as literal constants of octal numbers (base 8) and hexadecimal numbers (base 16). If we want to express an octal number we have to precede it with a 0 (zero character). And in order to express a hexadecimal number we have to precede it with the characters 0x (zero, x). For example, the following literal constants are all equivalent to each other:

75 // decimal 0113 // octal 0x4b // hexadecimal

Page 24: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

24 [email protected]

All of these represent the same number: 75 (seventy-five) expressed as a base-10 numeral, octal numeral and hexadecimal numeral, respectively.

Literal constants, like variables, are considered to have a specific data type. By default, integer literals are of type int. However, we can force them to either be unsigned by appending the u character to it, or long by appending l:

75 // int 75u // unsigned int 75l // long 75ul // unsigned long

In both cases, the suffix can be specified using either upper or lowercase letters.

Floating Point Numbers They express numbers with decimals and/or exponents. They can include either a decimal point, an e character (that expresses "by ten at the Xth height", where X is an integer value that follows the e character), or both a decimal point and an e character: 3.14159 // 3.14159 6.02e23 // 6.02 x 1023 1.6e-19 // 1.6 x 10-19 3.0 // 3.0

These are four valid numbers with decimals expressed in C++. The first number is PI, the second one is the number of Avogadro, the third is the electric charge of an electron (an extremely small number) -all of them approximated- and the last one is the number three expressed as a floating-point numeric literal.

The default type for floating point literals is double. If you explicitly want to express a float or long double numerical literal, you can use the f or l suffixes respectively:

3.14159L // long double 6.02e23f // float

Any of the letters than can be part of a floating-point numerical constant (e, f, l) can be written using either lower or uppercase letters without any difference in their meanings.

Character and string literals There also exist non-numerical constants, like: 'z'

Page 25: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

25 [email protected]

'p' "Hello world" "How do you do?"

The first two expressions represent single character constants, and the following two represent string literals composed of several characters. Notice that to represent a single character we enclose it between single quotes (') and to express a string (which generally consists of more than one character) we enclose it between double quotes (").

When writing both single character and string literals, it is necessary to put the quotation marks surrounding them to distinguish them from possible variable identifiers or reserved keywords. Notice the difference between these two expressions:

x 'x'

x alone would refer to a variable whose identifier is x, whereas 'x' (enclosed within single quotation marks) would refer to the character constant 'x'.

Character and string literals have certain peculiarities, like the escape codes. These are special characters that are difficult or impossible to express otherwise in the source code of a program, like newline (\n) or tab (\t). All of them are preceded by a backslash (\). Here you have a list of

some of such escape codes:

\n newline \r carriage return \t tab \v vertical tab \b backspace \f form feed (page feed) \a alert (beep) \' single quote (') \" double quote (") \? question mark (?) \\ backslash (\)

Page 26: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

26 [email protected]

For example:

'\n' '\t' "Left \t Right"

"one\ntwo\nthree"

Additionally, you can express any character by its numerical ASCII code by writing a backslash character (\) followed by the ASCII code expressed as an octal (base-8) or hexadecimal (base-16) number. In the first case (octal) the digits must immediately follow the backslash (for example \23 or \40), in the second case (hexadecimal), an x character must be written before the digits themselves (for example \x20 or \x4A).

String literals can extend to more than a single line of code by putting a backslash sign (\) at the end of each unfinished line.

"string expressed in \ two lines"

You can also concatenate several string constants separating them by one or several blank spaces, tabulators, newline or any other valid blank character:

"this forms" "a single" "string" "of characters"

Finally, if we want the string literal to be explicitly made of wide characters (wchar_t), instead of narrow characters (char), we can precede the constant with the L prefix:

L"This is a wide character string"

Wide characters are used mainly to represent non-English or exotic character sets.

Boolean literals There are only two valid Boolean values: true and false. These can be expressed in C++ as values of type bool by using the Boolean literals true and false.

Defined constants (#define)

Page 27: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

27 [email protected]

You can define your own names for constants that you use very often without having to resort to memory-consuming variables, simply by using the #define preprocessor directive. Its format is:

#define identifier value

For example:

#define PI 3.14159265 #define NEWLINE '\n'

This defines two new constants: PI and NEWLINE. Once they are defined, you can use them in the rest of the code as if they were any other regular constant, for example:

// defined constants: calculate circumference #include <iostream> using namespace std; #define PI 3.14159 #define NEWLINE '\n'; int main () { double r=5.0; // radius double circle; circle = 2 * PI * r; cout << circle; cout << NEWLINE; return 0; } 31.4159

In fact the only thing that the compiler preprocessor does when it encounters #define directives is to literally replace any occurrence of their identifier (in the previous example, these were PI and NEWLINE) by the code to which they have been defined (3.14159265 and '\n' respectively).

The #define directive is not a C++ statement but a directive for the preprocessor; therefore it assumes the entire line as the directive and does not require a semicolon (;) at its end. If you append a semicolon character (;) at the end, it will also be appended in all occurrences within the body of the program that the preprocessor replaces.

Page 28: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

28 [email protected]

Declared constants (const)

With the const prefix you can declare constants with a specific type in the same way as you would do with a variable: const int pathwidth = 100; const char tabulator = '\t';

const zipcode =12440;

In case that no type is explicitly specified (as in the last example) the compiler assumes that it is of type int.

String Stream

The standard header file <sstream> defines a class called stringstream that allows a string-based object to be treated as a stream. This way we can perform extraction or insertion operations from/to strings, which is especially useful to convert strings to numerical values and vice versa. For example, if we want to extract an integer from a string we can write: string mystr ("1204"); int myint; stringstream(mystr) >> myint;

This declares a string object with a value of "1204", and an int object. Then we use stringstream's constructor to construct an object of this type from the string object. Because we can use stringstream objects as if they were streams, we can extract an integer from it as we would have done on cin by applying the extractor operator (>>) on it followed by a variable of type int.

After this piece of code, the variable myint will contain the numerical value 1204.

// stringstreams #include <iostream> #include <string> #include <sstream> using namespace std;

type typical size description short 2 bytes stores a short (i.e., small) integer int 4 bytes stores an integer long 4 bytes stores a long (i.e., large) integer float 4 bytes stores a floating-point number double 8 bytes stores a "double-precision" floating-point number

Page 29: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

29 [email protected]

int main () { string mystr; float price=0; int quantity=0; cout << "Enter price: "; getline (cin,mystr); stringstream(mystr) >> price; cout << "Enter quantity: "; getline (cin,mystr); stringstream(mystr) >> quantity; cout << "Total price: " << price*quantity << endl; return 0; } Enter price: 22.25 Enter quantity: 7 Total price: 155.75

In this example, we acquire numeric values from the standard input indirectly. Instead of extracting numeric values directly from the standard input, we get lines from the standard input (cin) into a string object (mystr), and then we extract the integer values from this string into a variable of type int (myint).

Using this method, instead of direct extractions of integer values, we have more control over what happens with the input of numeric values from the user, since we are separating the process of obtaining input from the user (we now simply ask for lines) with the interpretation of that input. Therefore, this method is usually preferred to get numerical values from the user in all programs that are intensive in user input.

Example

#include "stdafx.h"

#include <iostream>

#include <string>

using namespace std;

int main ()

{

string mystr;

Page 30: C++ & VISUAL C++

cout << "What's your name? ";

getline (cin, mystr);

cout << "Hello " << mystr << ".

cout << "What is your favorite team? ";

getline (cin, mystr);

cout << "I like " << mystr << " too!

return 0;

}

Operators

Booleans: True and False

Before talking about operators, we'll take a quick aside into what a boolean is before discussing operators. A boolean value is one that can be either true or false. No other values are allowed. Booleans and boolean operations are at the heart of programming. Many times in a program, you'll want to do one thing if a certain and a different thing if the condition is false. For example, when processing a series of checkboxes, you may want to take an action only if a box is checked, and do notThat's when you'll want to use a boolean.

Most programming languages have a type for booleans, usually called "boolean" or "bool". Some C++ compilers recognize the type supports the bool type. We'll discuss what to do if your compiler doesn't, in a moment.

In order to use boolean logic to your advantage, you need to learn about the three basic boolean operations. They are called andinputs, and returns a boolean output. Theyshown below.

and

VISUAL C++ PROGRAMMING

[email protected]

cout << "What's your name? ";

cout << "Hello " << mystr << ".\n";

cout << "What is your favorite team? ";

< mystr << " too!\n";

Before talking about operators, we'll take a quick aside into booleans, since we'll need to know is before discussing operators. A boolean value is one that can be either true or

false. No other values are allowed. Booleans and boolean operations are at the heart of programming. Many times in a program, you'll want to do one thing if a certain and a different thing if the condition is false. For example, when processing a series of checkboxes, you may want to take an action only if a box is checked, and do notThat's when you'll want to use a boolean.

Most programming languages have a type for booleans, usually called "boolean" or "bool". Some C++ compilers recognize the type bool, others do not. For now, assume that your compiler

type. We'll discuss what to do if your compiler doesn't, in a moment.

In order to use boolean logic to your advantage, you need to learn about the three basic boolean and, or, and not. Each operation takes either one or two boolean

inputs, and returns a boolean output. They are often represented by symbols known as "gates",

The "and" operation takes two inputs and produces one output. If both inputs are true, the output is true; in all other cases, the output is false. It can be interpreted as follows: "I will return true if input 1 and

VISUAL C++ PROGRAMMING VC++

30

, since we'll need to know is before discussing operators. A boolean value is one that can be either true or

false. No other values are allowed. Booleans and boolean operations are at the heart of programming. Many times in a program, you'll want to do one thing if a certain condition is true, and a different thing if the condition is false. For example, when processing a series of checkboxes, you may want to take an action only if a box is checked, and do nothing otherwise.

Most programming languages have a type for booleans, usually called "boolean" or "bool". Some , others do not. For now, assume that your compiler

type. We'll discuss what to do if your compiler doesn't, in a moment.

In order to use boolean logic to your advantage, you need to learn about the three basic boolean . Each operation takes either one or two boolean are often represented by symbols known as "gates",

The "and" operation takes two inputs and produces one output. If both inputs are true, the output is true; in all other cases, the output is false. It can be interpreted as

and input 2 are true."

Page 31: C++ & VISUAL C++

or

not

Boolean operators in C++

There are operators in C++ which behave just as the boolean gates shown above! We'll show you an example of how to use each one.

and: &&

The "and" operator is used by placing

//suppose that Fran is tired bool franIsTired = true; //but Fran doesn't have to wake up early bool franMustWakeUpEarly = false; //will Fran go to sleep now? bool bedTime = franIsTired & What does this chunk of code do? It initializes two variables, franMustWakeUpEarly, to trueincluding comments!), we determine that Fran will go to sleep true -- that is, if both inputs to the "and" operation are true. In this case, the first input is true and the second input is false. Since "and" requires both inputs to be true in order for the output to be true, but one of the inputs is false, the output will be false. So, the variable store the value false.

Also, take note that the variable names used here are lengthy. How you decide to program is up to you, but often times it's better to have lengthieshort, obfuscated variable names like "i" or "zz". (The names in this example may have gone overboard, though.)

VISUAL C++ PROGRAMMING

[email protected]

The "or" operation takes two inputs and produces one output. If either of the inputs are true, the output is true; otherwise (i.e., if neither input is true), the output is false. It can be interpreted as follows: "I will return true if either input 1 or input 2 is true."

The "not" operation takes one input and produces one output. If the input is true, the output is false. If the input is false, the output is true. In other words, the "not" takes the input and returns its opposite.

There are operators in C++ which behave just as the boolean gates shown above! We'll show you an example of how to use each one.

The "and" operator is used by placing the "and" symbol, &&, in between two boolean values.

//but Fran doesn't have to wake up early

bool franMustWakeUpEarly = false;

bool bedTime = franIsTired && franMustWakeUpEarly;

What does this chunk of code do? It initializes two variables, franIsTired and true and false, respectively. Then, in the third line of code (not

including comments!), we determine that Fran will go to sleep if and only if the "and" operation is that is, if both inputs to the "and" operation are true. In this case, the first input is true

and the second input is false. Since "and" requires both inputs to be true in order for the output one of the inputs is false, the output will be false. So, the variable

Also, take note that the variable names used here are lengthy. How you decide to program is up to you, but often times it's better to have lengthier variable names that are readable, rather than short, obfuscated variable names like "i" or "zz". (The names in this example may have gone

VISUAL C++ PROGRAMMING VC++

31

The "or" operation takes two inputs and produces one output. If either of the inputs are true, the output is true; otherwise (i.e., if neither input is true), the output is false. It

"I will return true if either input 1

The "not" operation takes one input and produces one output. If the input is true, the output is false. If the input is false, the output is true. In other words, the "not" operation takes the input and returns its opposite.

There are operators in C++ which behave just as the boolean gates shown above! We'll show

, in between two boolean values.

and , respectively. Then, in the third line of code (not

the "and" operation is that is, if both inputs to the "and" operation are true. In this case, the first input is true

and the second input is false. Since "and" requires both inputs to be true in order for the output one of the inputs is false, the output will be false. So, the variable bedTime will

Also, take note that the variable names used here are lengthy. How you decide to program is up r variable names that are readable, rather than

short, obfuscated variable names like "i" or "zz". (The names in this example may have gone

Page 32: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

32 [email protected]

or: ||

The "or" operator is used by placing the "or" symbol, ||, in between two boolean values.

//suppose that Graham is tired bool grahamIsTired = true; //but Graham doesn't have to wake up early bool grahamMustWakeUpEarly = false; //will Graham go to sleep now? bool bedTime = grahamIsTired || grahamMustWakeUpEarly; This example is very similar to the example involving Fran, except notice the key difference: whether or not Graham goes to sleep is determined differently. Graham will go to sleep if he is tired or if he needs to wake up early. Whereas Fran would go to sleep only if both conditions were true, Graham will go to sleep if either condition (or both) is true. Therefore, the value of bedTime is true. not: !

The "not" operator is used by placing the "not" symbol, !, before a boolean value.

//suppose that Julian stayed up late bool julianStayedUpLate = true; //will Julian be peppy tomorrow? bool julianIsPeppy = !julianStayedUpLate; This example illustrates the "not" operator. At the end of this block of code, the variable julianIsPeppy will take on the opposite value of julianStayedUpLate. If julianStayedUpLate were false, then julianIsPeppy would be true. In this case, the opposite is true, so julianIsPeppy gets a value of false.

It is perfectly legal in C++ to use boolean operators on variables which are not booleans. In C++, "0" is false and any non-zero value is true. Let's look at a contrived example.

int hours = 4; int minutes = 21; int seconds = 0; bool timeIsTrue = hours && minutes && seconds; Since hours evaluates to true, and since minutes evaluates to true, and since seconds evaluates to false, the entire expression hours && minutes && seconds evaluates to false.

Page 33: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

33 [email protected]

Arithmetic operators in C++

In addition to the boolean operators, C++ has a number of arithmetic operators. Here they are:

Arithmetic operators

name symbol sample usage

addition + int sum = 4 + 7

subtraction - float difference = 18.55 - 14.21

multiplication * float product = 5 * 3.5

division / int quotient = 14 / 3

modulo ("mod") % int remainder = 10 % 6

They all probably look familiar with the exception of mod (%). The mod is simply the remainder produced by dividing two integers. In the example shown in the table above, if we treat 10 / 6 as an integer divison, the quotient is 1 (rather than 1.666) and the remainder is 4. Hence, the variable remainder will get the value 4.

Equality operators in C++

You are undoubtedly familiar with equality operators, even if you don't know it. An equality operator is one that tests a condition such as "is less than", "is greater than", and "is equal to". You will find it useful to be able to compare two numbers using expressions like "x is less than y".

Let's say you are writing software for a bank ATM (automated teller machine). A customer makes a request for a certain amount of cash, and your responsibility is to determine if they should be allowed to withdraw that amount. You could decide to use the following algorithm: "if the amount requested is less than the account balance, that amount should be withdrawn; otherwise, the customer should be notified and no money should be withdrawn." Makes sense, right? So, the next step is coming up with some pseudo-code. Once you have pseudo-code, writing the C++ code will be easy.

Pseudo-code for the ATM problem might look like this:

if the amount requested < account balance then withdraw the amount requested otherwise withdraw nothing and notify the customer Now that we have pseudo-code, writing the C++ code is as simple as "translating" your pseudo-code into C++. In this case, it's easy: if (amountRequested < accountBalance) {

Page 34: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

34 [email protected]

withdraw(amountRequested); } else { withdraw(0); notifyCustomer(); } You'll notice some new syntax in this example, but don't worry about it too much. Pay close attention to the very first line, which checks to make sure that the amount requested is less than the account balance. The way it works is, if the expression between parentheses (()) evaluates to true, then the first block of code will be read. That is, the code inside the first set of curly braces ({}) will be executed. If the expression in parentheses evaluates to false, on the other hand, then the second block of code (the code following the word else) will be read. In this case, the first block of code withdraws the amount requested by the customer, while the second block of code withdraws nothing, and notifies the customer.

That wasn't so hard! All we did was take the original English description of how we would solve the problem, write some pseudo-code for the English description, and translate the pseudo-code into C++.

Once you know how to use one equality operator, you know how to use all of them. They all work the same way: they take the expressions on either side of them, and either return true or false. Here they are:

Equality operators

name symbol sample usage result

is less than < bool result = (4 < 7) true

is greater than > bool result = (3.1 > 3.1) false

is equal to == bool result = (11 == 8) false

is less than or equal to <= bool result = (41.1 <= 42) true

is greater than or equal to >= bool result = (41.1 >= 42) false

is not equal to != bool result = (12 != 12) false

Assignment operators in C++

Believe it or not, you've already been using assignment operators! Probably the most common assignment operator is the equals sign (=). It is called "assignment" because you are "assigning" a variable to a value. This operator takes the expression on its right-hand-side and places it into the

Page 35: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

35 [email protected]

variable on its left-hand-side. So, when you write x = 5, the operator takes the expression on the right, 5, and stores it in the variable on the left, x.

Remember how the equality operators, like < and !=, returned a value that indicated the result? In that case, the return value was either true or false. In fact, almost every expression in C++ returns something! You don't always have to use the return value, though -- it's completely up to you. In the case of the assignment operators, the return value is simply the value that it stored in the variable on the left-hand-side.

Sometimes your code will use the return value to do something useful. In the ATM example, one line of code was executed if the condition was true (that is, if the equality operator returned true). Two different lines were executed if the condition was false.

Other times, you'll completely ignore the return value, because you're not interested in it. Take a look at the following code:

int x; int y; x = 5; y = 9; cout << "The value of x is " << x << endl; cout << "The value of y is " << y << endl; int sum; sum = x + y; cout << "The sum of x and y is " << sum << endl;

This chunk of code shows why you might want to throw away the return value of an operator. Look at the third line, x = 5. We're using the assignment operator here to place the value 5 in the variable x. Since the expression x = 5 returns a value, and we're not using it, then you could say we are ignoring the return value. However, note that a few of lines down, we are very interested in the return value of an operator. The addition operator in the expression x + y returns the sum of its left-hand-side and right-hand-side. That's how we are able to assign a value to sum. You can think of it as sum = (x + y), since that's what it's really doing.

The other assignment operators are all based on the equals sign, so make sure you understand that before going on. Here's another assignment operator: +=. How does it work? You might guess that it has something to do with addition, and something to do with assignment. You'd be absolutely right! The += operator takes the variable on its left-hand-side and adds the expression on its right-hand-side. Whenever you see a statement that looks like the following:

Page 36: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

36 [email protected]

myVar += something; it is identical to saying the following: myVar = myVar + something; That's exactly what it's doing! It's simply a shortcut.

The other common assignment operators are -=, *=, /=, and %=. They all function just like the += operator, except instead of adding the value on the right-hand-side, they subtract, or multiply, or divide, or "mod" it.

Just as the simple assignment operator = returns the value that it stored, all of the assignment operators return the value stored in the variable on the left-hand-side. Here's an example of how you might take advantage of this return value. It's not used terribly often, but it can sometimes be useful.

//these four variables represent the sides of a rectangle int left; int top; int right; int bottom; //make it a square whose sides are 4 left = top = right = bottom = 4; All this code does is store the value in each of the four variables left, top, right, and bottom. How does it work? It starts on the far right-hand side. It sees bottom = 4. So it places the value 4 in the variable bottom, and returns the value it stored in bottom (which is 4). Since bottom = 4 evaluates to 4, the variable right will also get the value 4, which means top will also get 4, which means left will also get 4. Phew! Of course, this code could have just as easily been written //these four variables represent the sides of a rectangle int left; int top; int right; int bottom; //make it a square whose sides are 4 left = 4; top = 4; right = 4; bottom = 4; Operator Precedence So far, we've seen a number of different operators. Here's a summary of the operators we've covered so far:

Boolean operators &&, ||, !

Page 37: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

37 [email protected]

Arithmetic operators +, -, *, /, % Equality operators <, >, ==, <=, >=, !=

Assignment operators =, +=, -=, *=, /=, %=

What is operator precedence?

Operator precedence refers to the order in which operators get used. An operator with high precedence will get used before an operator with lower precedence. Here's an example:

int result = 4 + 5 * 6 + 2; What will be the value of result? The answer depends on the precedence of the operators. In C++, the multiplication operator (*) has higher precedence than the addition operator (+). What that means is, the multiplication 5 * 6 will take place before either of the additions, so your expression will resolve to 4 + 30 + 2 , so result will store the value 36.

Since C++ doesn't really care about whitespace, the same thing would be true if you had written:

int result = 4+5 * 6+2; The result would still be 36.

Maybe you wanted to take the sum 4 + 5 and multiply it by the sum 6 + 2 for a result of 72? Just as in math class, add parentheses. You can write:

int result = (4 + 5) * (6 + 2);

Operator precedence in C++

Operator precedence in C++ is incredibly easy! Don't let anyone tell you otherwise! Here's the trick: if you don't know the order of precedence, or you're not sure, add parentheses! Don't even bother looking it up. We can guarantee that it will be faster for you to add parentheses than to look it up in this tutorial or in a C++ book. Adding parentheses has another obvious benefit - it makes your code much easier to read. Chances are, if you are uncertain about the order of precedence, anyone reading your code will have the same uncertainty.

That having been said, here's the order of operator precedence. In general, the order is what you would think it is - that is, you can safely say

int x = 4 + 3; and it will correctly add 4 and 3 before assigning to x. Our advice is to read this table once and then never refer to it again.

Operator precedence operators have the same precedence as other operators in their group, and higher precedence than

operators in lower groups

Page 38: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

38 [email protected]

operator name ! boolean not * multiplication / division % mod + addition - subtraction < is less than <= is less than or equal to > is greater than >= is greater than or equal to == is equal to != is not equal to

&& boolean and

|| boolean or = assignment *= multiply and assign /= divide and assign %= mod and assign += add and assign -= subtract and assign

Branching Statements (if, else, switch)

The if statement

The first type of branching statement we will look at is the if statement. An if statement has the form:

if (condition) { // code to execute if condition is true } else { // code to execute if condition is false } In an if statement, condition is a value or an expression that is used to determine which code block is executed, and the curly braces act as "begin" and "end" markers.

Here is a full C++ program as an example:

//include this file for cout #include <iostream.h>

Page 39: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

39 [email protected]

int main() { // define two integers int x = 3; int y = 4; //print out a message telling which is bigger if (x > y) { cout << "x is bigger than y" << endl; } else { cout << "x is smaller than y" << endl; } return 0; }

In this case condition is equal to "(x > y)" which is equal to "(3 > 4)" which is a false statement. So the code within the else clause will be executed. The output of this program will be:

x is smaller than y If instead the value for x was 6 and the value for y was 2, then condition would be "(6 > 2)" which is a true statement and the output of the program would be: x is bigger than y

the switch statement

The next branching statement is called a switch statement. A switch statement is used in place of many if statements.

Let's consider the following case: Joel is writing a program that figures interest on money that is held in a bank. The amount of interest that money earns in this bank depends on which type of account the money is in. There are 6 different types of accounts and they earn interest as follows:

account type interest earned

personal financial 2.3%

personal homeowner 2.6%

personal gold 2.9%

small business 3.3%

big business 3.5%

gold business 3.8%

Page 40: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

40 [email protected]

One way for Joel to write this program is as follows: (assuming also that Joel has assigned numbers to the account types starting with personal financial and ending with gold business.)

// declare a variable to keep track of the interest float interest = 0.0; // decide which interest rate to use. if (account_type == 1){ interest = 2.3; } else { if (account_type == 2) { interest = 2.6; } else { if (account_type == 3){ interest = 2.9; } else { if (account_type == 4){ interest = 3.3; } else { if (account_type == 5){ interest = 3.5; } else { // account type must be 6 interest = 3.8; } } } } }

That code is hard to read and hard to understand. There is an easier way to write this, using the switch statement. The preceding chunk of code could be written as follows:

switch (account_value){ case 1: interest = 2.3; break; case 2: interest = 2.6; break; case 3: interest = 2.9;

Page 41: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

41 [email protected]

break; case 4: interest = 3.3; break; case 5: interest = 3.5; break; case 6: interest = 3.8; break; default: interest = 0.0; }

The switch statement allows a programmer to compound a group of if statements, provided that the condition being tested is an integer. The switch statement has the form:

switch(integer_val){ case val_1: // code to execute if integer_val is val_1 break; ... case val_n: // code to execute if integer_val is val_n break; default: // code to execute if integer_val is none of the above }

The default clause is optional, but it is good programming practice to use it. The default clause is executed if none of the other clauses have been executed. For example, if my code looked like:

switch (place) { case 1: cout << "we're first" << endl; break; case 2: cout << "we're second" << endl; break; default: cout << "we're not first or second" << endl; }

Page 42: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

42 [email protected]

This switch statement will write "we're first" if the variable place is equal to 1, it will write "we're second" if place is equal to 2, and will write "we're not first or second" if place is any other value.

The break keyword means "jump out of the switch statement, and do not execute any more code." To show how this works, examine the following piece of code:

int value = 0; switch(input){ case 1: value+=4; case 2: value+=3; case 3: value+=2; default: value++; }

If input is 1 then 4 will be added to value. Since there is no break statement, the program will go on to the next line of code which adds 3, then the line of code that adds 2, and then the line of code that adds 1. So value will be set to 10! The code that was intended was probably:

int value = 0; switch(input){ case 1: value+=4; break; case 2: value+=3; break; case 3: value+=2; break; default: value++; }

This feature of switch statements can sometimes be used to a programmers' advantage. In the example with the different types of bank accounts, say that the interest earned was a follows:

account type interest earned

personal financial 2.3%

personal homeowner 2.6%

personal gold 2.9%

Page 43: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

43 [email protected]

small business 2.6%

big business 2.9%

gold business 3.0%

Now, the code for this could be written as:

switch (account_value){ case 1: interest = 2.3; break; case 2: case 4: interest = 2.6; break; case 3: case 5: interest = 2.9; break; case 6: interest = 3.8; break; default: interest = 0.0; }

#include <iostream>

using namespace std;

int main(int argc, char *argv[])

{

switch( tolower( *argv[1] ) )

{

// Error. Unreachable declaration.

char szChEntered[] = "Character entered was: ";

case 'a' :

{

// Declaration of szChEntered OK. Local scope.

Page 44: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

44 [email protected]

char szChEntered[] = "Character entered was: ";

cout << szChEntered << "a\n"; } break; case 'b' :

// Value of szChEntered undefined.

cout << szChEntered << "b\n";

break;

default:

// Value of szChEntered undefined.

cout << szChEntered << "neither a nor b\n"; break;

}

}

Control Structures

A program is usually not limited to a linear sequence of instructions. During its process it may bifurcate, repeat code or take decisions. For that purpose, C++ provides control structures that serve to specify what has to be done by our program, when and under which circumstances.

With the introduction of control structures we are going to have to introduce a new concept: the compound-statement or block. A block is a group of statements which are separated by semicolons (;) like all C++ statements, but grouped together in a block enclosed in braces: { }:

{ statement1; statement2; statement3; }

Most of the control structures that we will see in this section require a generic statement as part of its syntax. A statement can be either a simple statement (a simple instruction ending with a semicolon) or a compund statement (several instructions grouped in a block), like the one just described. In the case that we want the statement to be a simple statement, we do not need to enclose it in braces ({}). But in the case that we want the statement to be a compund statement it must be enclosed between braces ({}), forming a block.

Conditional structure: if and else

The if keyword is used to execute a statement or block only if a condition is fulfilled. Its form is:

if (condition) statement

Page 45: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

45 [email protected]

Where condition is the expression that is being evaluated. If this condition is true, statement is executed. If it is false, statement is ignored (not executed) and the program continues right after this conditional structure. For example, the following code fragment prints x is 100 only if the value stored in the x variable is indeed 100:

if (x == 100)

cout << "x is 100";

If we want more than a single statement to be executed in case that the condition is true we can specify a block using braces { }:

if (x == 100) { cout << "x is "; cout << x;

}

We can additionally specify what we want to happen if the condition is not fulfilled by using the keyword else. Its form used in conjunction with if is:

if (condition) statement1 else statement2

For example:

if (x == 100) cout << "x is 100"; else

cout << "x is not 100";

prints on the screen x is 100 if indeed x has a value of 100, but if it has not -and only if not- it prints out x is not 100.

The if + else structures can be concatenated with the intention of verifying a range of values. The following example shows its use telling if the value currently stored in x is positive, negative or none of them (i.e. zero):

Page 46: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

46 [email protected]

if (x > 0) cout << "x is positive"; else if (x < 0) cout << "x is negative"; else

cout << "x is 0";

Remember that in case that we want more than a single statement to be executed, we must group them in a block by enclosing them in braces { }.

Loops (for, while, do)

Iteration structures (loops)

Loops have as purpose to repeat a statement a certain number of times or while a condition is fulfilled.

The while loop Its format is:

while (expression) statement and its functionality is simply to repeat statement while the condition set in expression is true.

For example, we are going to make a program to countdown using a while-loop:

// custom countdown using while #include <iostream> using namespace std; int main () { int n; cout << "Enter the starting number > "; cin >> n; while (n>0) { cout << n << ", "; --n; } cout << "FIRE!\n"; return 0; } Enter the starting number > 8 8, 7, 6, 5, 4, 3, 2, 1, FIRE!

Page 47: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

47 [email protected]

When the program starts the user is prompted to insert a starting number for the countdown. Then the while loop begins, if the value entered by the user fulfills the condition n>0 (that n is greater than zero) the block that follows the condition will be executed and repeated while the condition (n>0) remains being true.

The whole process of the previous program can be interpreted according to the following script (beginning in main):

1. User assigns a value to n 2. The while condition is checked (n>0). At this point there are two posibilities:

* condition is true: statement is executed (to step 3) * condition is false: ignore statement and continue after it (to step 5)

3. Execute statement: cout << n << ", "; --n; (prints the value of n on the screen and decreases n by 1)

4. End of block. Return automatically to step 2 5. Continue the program right after the block: print FIRE! and end program.

When creating a while-loop, we must always consider that it has to end at some point, therefore we must provide within the block some method to force the condition to become false at some point, otherwise the loop will continue looping forever. In this case we have included --n; that decreases the value of the variable that is being evaluated in the condition (n) by one - this will eventually make the condition (n>0) to become false after a certain number of loop iterations: to be more specific, when n becomes 0, that is where our while-loop and our countdown end.

Of course this is such a simple action for our computer that the whole countdown is performed instantly without any practical delay between numbers.

The do-while loop

Its format is:

do statement while (condition);

Its functionality is exactly the same as the while loop, except that condition in the do-while loop is evaluated after the execution of statement instead of before, granting at least one execution of statement even if condition is never fulfilled. For example, the following example program echoes any number you enter until you enter 0.

// number echoer #include <iostream> using namespace std;

Page 48: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

48 [email protected]

int main () { unsigned long n; do { cout << "Enter number (0 to end): "; cin >> n; cout << "You entered: " << n << "\n"; } while (n != 0); return 0; } Enter number (0 to end): 12345 You entered: 12345 Enter number (0 to end): 160277 You entered: 160277 Enter number (0 to end): 0 You entered: 0

The do-while loop is usually used when the condition that has to determine the end of the loop is determined within the loop statement itself, like in the previous case, where the user input within the block is what is used to determine if the loop has to end. In fact if you never enter the value 0 in the previous example you can be prompted for more numbers forever.

The for loop

Its format is:

for (initialization; condition; increase) statement;

and its main function is to repeat statement while condition remains true, like the while loop. But in addition, the for loop provides specific locations to contain an initialization statement and an increase statement. So this loop is specially designed to perform a repetitive action with a counter which is initialized and increased on each iteration.

It works in the following way:

1. initialization is executed. Generally it is an initial value setting for a counter variable. This is executed only once.

2. condition is checked. If it is true the loop continues, otherwise the loop ends and statement is skipped (not executed).

3. statement is executed. As usual, it can be either a single statement or a block enclosed in braces { }.

4. finally, whatever is specified in the increase field is executed and the loop gets back to step 2.

Page 49: C++ & VISUAL C++

Here is an example of countdown using a for loop: // countdown using a for loop#include <iostream> using namespace std; int main () { for (int n=10; n>0; n--) { cout << n << ", "; } cout << "FIRE!\n"; return 0;

}

The initialization and increase fields are optional. They can remain empty, but in all cases the semicolon signs between them must be written. For example we could write: wanted to specify no initialization and no increase; or an increase field but no initialization (maybe because the variable

Optionally, using the comma operator (fields included in a for loop, like in expression separator, it serves to separate more than one expression where only one is generally expected. For example, suppose that we wanted to initialize more than one variable in our loop: for ( n=0, i=100 ; n!=i ; n++, i{ // whatever here...

}

This loop will execute for 50 times if neither

n starts with a value of 0, and i is increased by one and i decreased by one, the loop's condition will become false after tloop, when both n and i will be equal to

Jump statements.

VISUAL C++ PROGRAMMING

[email protected]

Here is an example of countdown using a for loop: a for loop

fields are optional. They can remain empty, but in all cases the semicolon signs between them must be written. For example we could write: wanted to specify no initialization and no increase; or for (;n<10;n++) if we wanted to include an increase field but no initialization (maybe because the variable was already initialized before).

Optionally, using the comma operator (,) we can specify more than one expression in any of the loop, like in initialization, for example. The comma operator (

ves to separate more than one expression where only one is generally expected. For example, suppose that we wanted to initialize more than one variable in our loop:

( n=0, i=100 ; n!=i ; n++, i-- )

r 50 times if neither n or i are modified within the loop:

with 100, the condition is n!=i (that n is not equal to decreased by one, the loop's condition will become false after twill be equal to 50.

VISUAL C++ PROGRAMMING VC++

49

fields are optional. They can remain empty, but in all cases the semicolon signs between them must be written. For example we could write: for (;n<10;) if we

if we wanted to include was already initialized before).

) we can specify more than one expression in any of the , for example. The comma operator (,) is an

ves to separate more than one expression where only one is generally expected. For example, suppose that we wanted to initialize more than one variable in our loop:

are modified within the loop:

is not equal to i). Because n decreased by one, the loop's condition will become false after the 50th

Page 50: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

50 [email protected]

The break statement

Using break we can leave a loop even if the condition for its end is not fulfilled. It can be used to end an infinite loop, or to force it to end before its natural end. For example, we are going to stop the count down before its natural end (maybe because of an engine check failure?):

// break loop example #include <iostream> using namespace std; int main () { int n; for (n=10; n>0; n--) { cout << n << ", "; if (n==3) { cout << "countdown aborted!"; break; } } return 0; } The continue statement

The continue statement causes the program to skip the rest of the loop in the current iteration as if the end of the statement block had been reached, causing it to jump to the start of the following iteration. For example, we are going to skip the number 5 in our countdown:

// continue loop example #include <iostream> using namespace std; int main () { for (int n=10; n>0; n--) { if (n==5) continue; cout << n << ", "; } cout << "FIRE!\n"; return 0; } The goto statement goto allows to make an absolute jump to another point in the program. You should use this feature with caution since its execution causes an unconditional jump ignoring any type of nesting limitations.

Page 51: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

51 [email protected]

The destination point is identified by a label, which is then used as an argument for the goto statement. A label is made of a valid identifier followed by a colon (:).

Generally speaking, this instruction has no concrete use in structured or object oriented programming aside from those that low-level programming fans may find for it. For example, here is our countdown loop using goto:

// goto loop example #include <iostream> using namespace std; int main () { int n=10; loop: cout << n << ", "; n--; if (n>0) goto loop; cout << "FIRE!\n"; return 0; } The exit function

exit is a function defined in the cstdlib library.

The purpose of exit is to terminate the current program with a specific exit code. Its prototype is:

void exit (int exitcode);

The exitcode is used by some operating systems and may be used by calling programs. By convention, an exit code of 0 means that the program finished normally and any other value means that some error or unexpected results happened.

The selective structure: switch.

The syntax of the switch statement is a bit peculiar. Its objective is to check several possible constant values for an expression. Something similar to what we did at the beginning of this section with the concatenation of several if and else if instructions. Its form is the following: switch (expression) { case constant1: group of statements 1; break; case constant2: group of statements 2; break;

Page 52: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

52 [email protected]

. . . default: default group of statements }

It works in the following way: switch evaluates expression and checks if it is equivalent to constant1, if it is, it executes group of statements 1 until it finds the break statement. When it finds this break statement the program jumps to the end of the switch selective structure.

If expression was not equal to constant1 it will be checked against constant2. If it is equal to this, it will execute group of statements 2 until a break keyword is found, and then will jump to the end of the switch selective structure.

Finally, if the value of expression did not match any of the previously specified constants (you can include as many case labels as values you want to check), the program will execute the statements included after the default: label, if it exists (since it is optional).

Both of the following code fragments have the same behavior:

switch example if-else equivalent switch (x) { case 1: cout << "x is 1"; break; case 2: cout << "x is 2"; break; default: cout << "value of x unknown"; }

if (x == 1) { cout << "x is 1"; } else if (x == 2) { cout << "x is 2"; } else { cout << "value of x unknown"; }

The switch statement is a bit peculiar within the C++ language because it uses labels instead of blocks. This forces us to put break statements after the group of statements that we want to be executed for a specific condition. Otherwise the remainder statements -including those corresponding to other labels- will also be executed until the end of the switch selective block or a break statement is reached.

Page 53: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

53 [email protected]

For example, if we did not include a break statement after the first group for case one, the program will not automatically jump to the end of the switch selective block and it would continue executing the rest of statements until it reaches either a break instruction or the end of the switch selective block. This makes unnecessary to include braces { } surrounding the statements for each of the cases, and it can also be useful to execute the same block of instructions for different possible values for the expression being evaluated. For example:

switch (x) { case 1: case 2: case 3: cout << "x is 1, 2 or 3"; break; default: cout << "x is not 1, 2 nor 3";

}

Notice that switch can only be used to compare an expression against constants. Therefore we cannot put variables as labels (for example case n: where n is a variable) or ranges (case (1..3):) because they are not valid C++ constants.

If you need to check ranges or values that are not constants, use a concatenation of if and else if statements.

The for statement

the for statement has the form: for(initial_value,test_condition,step){ // code to execute inside loop };

• initial_value sets up the initial value of the loop counter. • test_condition this is the condition that is tested to see if the loop is executed again. • step this describes how the counter is changed on each execution of the loop.

Here is an example:

// The following code adds together the numbers 1 through 10 // this variable keeps the running total int total=0; // this loop adds the numbers 1 through 10 to the variable total for (int i=1; i < 11; i++){ total = total + i; }

Page 54: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

54 [email protected]

So in the preceding chunk of code we have:

• initial_condition is int i=0; • test_condition is i < 11; • step is i++;

So, upon initial execution of the loop, the integer variable i is set to 1. The statement total = total + i; is executed and the value of the variable total becomes 1. The step code is now executed and i is incremented by 1, so its new value is 2.

The test_condition is then checked, and since i is less than 11, the loop code is executed and the variable total gets the value 3 (since total was 1, and i was 2. i is then incremented by 1 again.

The loop continues to execute until the condition i<11 fails. At that point total will have the value 1+2+3+4+5+6+7+8+9+10 = 55.

The while statement

The while statement has the form: while(condition) { // code to execute };

• condition is a boolean statement that is checked each time after the final "}" of the while statement executes. If the condition is true then the while statement executes again. If the condition is false, the while statement does not execute again.

As an example, let's say that we wanted to write all the even numbers between 11 and 23 to the screen. The following is a full C++ program that does that.

// include this file for cout #include <iostream.h> int main(){ // this variable holds the present number int current_number = 12; // while loop that prints all even numbers between // 11 and 23 to the screen while (current_number < 23){ cerr << current_number << endl; current_number += 2; } cerr << "all done" << endl; }

Page 55: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

55 [email protected]

The preceding example prints the value of current_number to the screen and then adds 2 to its value. As soon as the value of the variable current_number goes above 23, the while loop exits and the next line is executed.

The output of the preceding program would be:

12 14 16 18 20 22 All done The program to display Fibonacci series until i=14 // fibo.cpp : Defines the entry point for the console application. // #include "stdafx.h" # include "iostream.h" int main() { int curr,prev,next,i=0; prev=0; curr=1; cout<<prev<<" "; for(i=0;i<15;i++) { next=curr+prev; curr=prev; prev=next; cout<<next<<" "; } cout<<endl; return 0; }

Page 56: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

56 [email protected]

C++ Scope Resolution Operator ::

The :: (scope resolution) operator is used to qualify hidden names so that you can still use

them. You can use the unary scope operator if a namespace scope or global scope name is

hidden by an explicit declaration of the same name in a block or class. For example:

int count = 0;

int main(void) {

int count = 0;

::count = 1; // set global count to 1

count = 2; // set local count to 2

return 0;

}

The declaration of count declared in the main() function hides the integer named count

declared in global namespace scope. The statement ::count = 1 accesses the variable

named count declared in global namespace scope.

You can also use the class scope operator to qualify class names or class member names. If a

class member name is hidden, you can use it by qualifying it with its class name and the class

scope operator.

In the following example, the declaration of the variable X hides the class type X, but you can

still use the static class member count by qualifying it with the class type X and the scope

resolution operator.

#include <iostream>

using namespace std;

class X

{

public:

static int count;

};

Page 57: C++ & VISUAL C++

int X::count = 10; // define sta

int main ()

{

int X = 0; // hides class type X

cout << X::count << endl; // use static member of class X

}

C++ Memory Management Operators

Need for Memory Management operators

The concept of arrays has a block of memory reserved. The disadvantage with the concept of

arrays is that the programmer must know, while programming, the size of memory to be

allocated in addition to the array

In programming there may be scenarios where programmers may not know the memory

needed until run time. In this case, the programmer can opt to reserve as much memory as

possible, assigning the maximum memory space needed to tackl

result in wastage of unused memory spaces. Memory

handle this situation in C++ programming language.

What are memory management operators?

There are two types of memory

• new

• delete

These two memory management operators are used for allocating and freeing memory blocks

in efficient and convenient ways.

New operator:

The new operator in C++ is used for dynamic storage allocation. This operator can be used to

create object of any type.

General syntax of new operator in C++:

The general syntax of new operator in C++ is as follows:

pointer variable = new datatype;

In the above statement, new is a keyword and the pointer variable is a variable of type

datatype.

For example:

VISUAL C++ PROGRAMMING

[email protected]

int X::count = 10; // define static data member

int X = 0; // hides class type X

cout << X::count << endl; // use static member of class X

C++ Memory Management Operators

Need for Memory Management operators

The concept of arrays has a block of memory reserved. The disadvantage with the concept of

arrays is that the programmer must know, while programming, the size of memory to be

allocated in addition to the array size remaining constant.

In programming there may be scenarios where programmers may not know the memory

needed until run time. In this case, the programmer can opt to reserve as much memory as

possible, assigning the maximum memory space needed to tackle this situation. This would

result in wastage of unused memory spaces. Memory management operators are used to

handle this situation in C++ programming language.

What are memory management operators?

memory management operators in C++:

These two memory management operators are used for allocating and freeing memory blocks

in efficient and convenient ways.

or in C++ is used for dynamic storage allocation. This operator can be used to

General syntax of new operator in C++:

The general syntax of new operator in C++ is as follows:

pointer variable = new datatype;

ement, new is a keyword and the pointer variable is a variable of type

VISUAL C++ PROGRAMMING VC++

57

tic data member

cout << X::count << endl; // use static member of class X

The concept of arrays has a block of memory reserved. The disadvantage with the concept of

arrays is that the programmer must know, while programming, the size of memory to be

In programming there may be scenarios where programmers may not know the memory

needed until run time. In this case, the programmer can opt to reserve as much memory as

e this situation. This would

ators are used to

These two memory management operators are used for allocating and freeing memory blocks

or in C++ is used for dynamic storage allocation. This operator can be used to

ement, new is a keyword and the pointer variable is a variable of type

Page 58: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

58 [email protected]

int *a=new int;

In the above example, the new operator allocates sufficient memory to hold the object of

datatype int and returns a pointer to its starting point. The pointer variable a holds the address

of memory space allocated.

Dynamic variables are never initialized by the compiler. Therefore, the programmer should

make it a practice to first assign them a value.

The assignment can be made in either of the two ways:

Sample Code

1. int *a = new int;

2. *a = 20;

Copyright exforsys.com

or

Sample Code

1. int *a = new int(20);

Copyright exforsys.com

delete operator:

The delete operator in C++ is used for releasing memory space when the object is no longer

needed. Once a new operator is used, it is efficient to use the corresponding delete operator

for release of memory.

General syntax of delete operator in C++:

The general syntax of delete operator in C++ is as follows:

delete pointer variable;

In the above example, delete is a keyword and the pointer variable is the pointer that points to

the objects already created in the new operator. Some of the important points the programmer

must note while using memory management operators are described below:

• The programmer must take care not to free or delete a pointer variable that has

already been deleted.

• Overloading of new and delete operator is possible (to be discussed in detail in later

section on overloading).

Page 59: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

59 [email protected]

• We know that sizeof operator is used for computing the size of the object. Using

memory management operator, the size of the object is automatically computed.

• The programmer must take care not to free or delete pointer variables that have not

been allocated using a new operator.

• Null pointer is returned by the new operator when there is insufficient memory

available for allocation.

Example:

To understand the concept of new and delete memory management operator in C++:

Sample Code

1. #include <iostream>

2. using namespace std;

3. void main()

4. {

5. //Allocates using new operator memory space in memory for storing a

integer datatype

6. int *a= new int;

7. *a=100;

8. cout << " The Output is:a= " << *a;

9. //Memory Released using delete operator

10. delete a; 11. 12. }

Copyright exforsys.com

The output of the above program is

In the above program, the statement:

int *a= new a;

Holds memory space in memory for storing a integer datatype. The statement:

*a=100

This denotes that the value present in address location pointed by the pointer variable a is 100

and this value of a is printed in the output statement giving the output shown in the example

Page 60: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

60 [email protected]

above. The memory allocated by the new operator for storing the integer variable pointed by

a is released using the delete operator as:

Ads

delete a;

Manipulators In C++

Manipulators Manipulators are operators used with the insertion operator << to modify or manipulate the

way data is displayed. It just changes certain characteristics of the input and output.

The following are the manipulators used in c++:-

• Endl

It is a manipulator that causes a line feed to be inserted into the stream. It I similar to ‘\n’

character.E.g. Cout<<”a=”<<a<<endl;

// Program to display a message on two new lines using the endl manipulator

#include<iostream.h>

#include<conio.h>

Void main ()

{

Cout<<”hello”<<endl;

Cout<<”many greetings”<<endl;

getch ();

}

• Setw()

This Setw () stands for the set width. The Setw () manipulator is used to set the width of the

word to be displayed on screen. The general form of Setw () is:-

Setw (int w)

Where, the integer inside the bracket indicates the total field width.

E.g. // demonstrate Setw () manipulator

#include<iostream.h>

#include<iomanip.h> // for Setw ()

#include<conio.h>

Page 61: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

61 [email protected]

Void main ()

{

Cout<<Setw (10) <<”name”<<Setw (10) <<”marks”<<endl;

Cout<<Setw (10) <<”ram”<<Setw (10) <<”95”<<endl;

Cout<<Setw (10) <<”hari”<<Setw (10) <<”85”<<endl;

getch ();

}

Operator Overloading in C++

In C++ the overloading principle applies not only to functions, but to operators too. That is,

of operators can be extended to work not just with built-in types but also classes. A

programmer can provide his or her own operator to a class by overloading the built-in

operator to perform some specific computation when the operator is used on objects of that

class. Is operator overloading really useful in real world implementations? It certainlly can

be, making it very easy to write code that feels natural (we'll see some examples soon). On

the other hand, operator overloading, like any advanced C++ feature, makes the language

more complicated. In addition, operators tend to have very specific meaning, and most

programmers don't expect operators to do a lot of work, so overloading operators can be

abused to make code unreadable. But we won't do that.

An Example of Operator Overloading

Complex a(1.2,1.3); //this class is used to represent complex numbers

Complex b(2.1,3); //notice the construction taking 2 parameters for

the real and imaginary part

Complex c = a+b; //for this to work the addition operator must be

overloaded

The addition without having overloaded operator + could look like this: Complex c = a.Add(b);

This piece of code is not as readable as the first example though--we're dealing with numbers,

so doing addition should be natural. (In contrast to cases when programmers abuse this

technique, when the concept represented by the class is not related to the operator--ike using

+ and - to add and remove elements from a data structure. In this cases operator overloading

is a bad idea, creating confusion.)

In order to allow operations like Complex c = a+b, in above code we overload the "+"

operator. The overloading syntax is quite simple, similar to function overloading, the

keyword operator must be followed by the operator we want to overload: class Complex

{

public:

Complex(double re,double im)

:real(re),imag(im)

{};

Complex operator+(const Complex& other);

Complex operator=(const Complex& other);

Page 62: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

62 [email protected]

private:

double real;

double imag;

};

Complex Complex::operator+(const Complex& other)

{

double result_real = real + other.real;

double result_imaginary = imag + other.imag;

return Complex( result_real, result_imaginary );

}

The assignment operator can be overloaded similarly. Notice that we did not have to call any

accessor functions in order to get the real and imaginary parts from the parameter other since

the overloaded operator is a member of the class and has full access to all private data.

Alternatively, we could have defined the addition operator globally and called a member to

do the actual work. In that case, we'd also have to make the method a friend of the class, or

use an accessor method to get at the private data: friend Complex operator+(Complex);

Complex operator+(const Complex &num1, const Complex &num2)

{

double result_real = num1.real + num2.real;

double result_imaginary = num1.imag + num2.imag;

return Complex( result_real, result_imaginary );

}

Why would you do this? when the operator is a class member, the first object in the

expression must be of that particular type. It's as if you were writing: Complex a( 1, 2 );

Complex a( 2, 2 );

Complex c = a.operator=( b );

when it's a global function, the implicit or user-defined conversion can allow the operator to

act even if the first operand is not exactly of the same type: Complex c = 2+b; //if the integer 2 can be converted by the Complex

class, this expression is valid

By the way, the number of operands to a function is fixed; that is, a binary operator takes two

operands, a unary only one, and you can't change it. The same is true for the precedence of

operators too; for example the multiplication operator is called before addition. There are

some operators that need the first operand to be assignable, such as : operator=, operator(),

operator[] and operator->, so their use is restricted just as member functions(non-static), they

can't be overloaded globally. The operator=, operator& and operator, (sequencing) have

already defined meanings by default for all objects, but their meanings can be changed by

overloading or erased by making them private.

Another intuitive meaning of the "+" operator from the STL string class which is overloaded

to do concatenation: string prefix("de");

string word("composed");

string composed = prefix+word;

Using "+" to concatenate is also allowed in Java, but note that this is not extensible to other

classes, and it's not a user defined behavior. Almost all operators can be overloaded in C++:

+ - * / % ^ & |

~ ! , = =

++ -- << >> == != && ||

+= -= /= %= ^= & = |= *=

<<= >>= [ ] ( ) -> ->* new delete

Page 63: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

63 [email protected]

The only operators that can't be overloaded are the operators for scope resolution (::),

member selection (.), and member selection through a pointer to a function(.*). Overloading

assumes you specify a behavior for an operator that acts on a user defined type and it can't be

used just with general pointers. The standard behavior of operators for built-in (primitive)

types cannot be changed by overloading, that is, you can't overload operator+(int,int).

The logic(boolean) operators have by the default a short-circuiting way of acting in

expressions with multiple boolean operations. This means that the expression: if(a && b && c)

will not evaluate all three operations and will stop after a false one is found. This behavior

does not apply to operators that are overloaded by the programmer.

Even the simplest C++ application, like a "hello world" program, is using overloaded

operators. This is due to the use of this technique almost everywhere in the standard library

(STL). Actually the most basic operations in C++ are done with overloaded operators, the

IO(input/output) operators are overloaded versions of shift operators(<<, >>). Their use

comes naturally to many beginning programmers, but their implementation is not

straightforward. However a general format for overloading the input/output operators must be

known by any C++ developer. We will apply this general form to manage the input/output for

our Complex class: friend ostream &operator<<(ostream &out, Complex c) //output

{

out<<"real part: "<<real<<"\n";

out<<"imag part: "<<imag<<"\n";

return out;

}

friend istream &operator>>(istream &in, Complex &c) //input

{

cout<<"enter real part:\n";

in>>c.real;

cout<<"enter imag part: \n";

in>>c.imag;

return in;

}

Notice the use of the friend keyword in order to access the private members in the above

implementations. The main distinction between them is that the operator>> may encounter

unexpected errors for incorrect input, which will make it fail sometimes because we haven't

handled the errors correctly. A important trick that can be seen in this general way of

overloading IO is the returning reference for istream/ostream which is needed in order to use

them in a recursive manner: Complex a(2,3);

Complex b(5.3,6);

cout<<a<<b;

C++ Operator Precedence

It is important to understand that operators have a precedence, but it is not essential to

memorize the precedence.

Page 64: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

64 [email protected]

Definition: Precedence is the order in which a program performs the operations in a

formula. If one operator has precedence over another operator, it is evaluated first.

Higher precedence operators "bind tighter" than lower precedence operators; thus, higher

precedence operators are evaluated first. The lower the rank in the following chart, the higher

the precedence.

The following table lists the precedence and associativity of C++ operators. Operators are

listed top to bottom, in descending precedence.

Precedence Operator Description Associativity

1 :: Scope resolution Left-to-right

2

++ -- Suffix/postfix increment and decrement

() Function call

[] Array subscripting

. Element selection by reference

−> Element selection through pointer

3

++ -- Prefix increment and decrement Right-to-left

+ − Unary plus and minus

! ~ Logical NOT and bitwise NOT

(type) Type cast

* Indirection (dereference)

& Address-of

sizeof Size-of

new, new[] Dynamic memory allocation

delete, delete[]

Dynamic memory deallocation

4 .* ->* Pointer to member Left-to-right

5 * / % Multiplication, division, and remainder

6 + − Addition and subtraction

7 << >> Bitwise left shift and right shift

8 < <= For relational operators < and ≤ respectively

> >= For relational operators > and ≥ respectively

9 == != For relational = and ≠ respectively

10 & Bitwise AND

11 ^ Bitwise XOR (exclusive or)

12 | Bitwise OR (inclusive or)

13 && Logical AND

14 || Logical OR

15 ?: Ternary conditional Right-to-left

Page 65: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

65 [email protected]

= Direct assignment (provided by default for C++

classes)

+= −= Assignment by sum and difference

*= /= %= Assignment by product, quotient, and remainder

<<= >>= Assignment by bitwise left shift and right shift

&= ^= |= Assignment by bitwise AND, XOR, and OR

16 throw Throw operator (for exceptions)

17 , Comma Left-to-right

When parsing an expression, an operator which is listed on some row will be bound tighter

(as if by parentheses) to its arguments than any operator that is listed on a row further below

it. For example, the expressions std::cout<<a&b and *p++ are parsed as (std::cout<<a)&b

and *(p++), and not as std::cout<<(a&b) or (*p)++.

Operators that are in the same cell (there may be several rows of operators listed in a cell) are

evaluated with the same precedence, in the given direction. For example, the expression

a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity.

An operator's precedence is unaffected by overloading.

Type Cast Operator: (type)

cast-expression :

unary-expression

( type-name ) cast-expression

A type cast provides a method for explicit conversion of the type of an object in a specific

situation.

The compiler treats cast-expression as type type-name after a type cast has been made. Casts

can be used to convert objects of any scalar type to or from any other scalar type. Explicit

type casts are constrained by the same rules that determine the effects of implicit conversions.

Additional restraints on casts may result from the actual sizes or representation of specific

types.

Example

In the following example, the type cast operator converts the float value of 3.1 to an integer

value of 3.

// Example of the type cast operator

float x = 3.1;

int i;

i = (int)x; // the value of i is now 3

Page 66: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

66 [email protected]

Unit 4: Functions, classes and objects(25 HOURS)

THEORY At the end of the unit the student should be able to: 1. ..know the main function 2. ..know and employ function prototyping 3. ..call a function by reference 4. ..return a function by reference 5. ..know what inline functions are 6. ..know what default arguments and constant arguments are 7. ..give examples of function overloading 8. ..explain what friend and virtual functions are 9. ..describe what structures in C are 10. ..specify a class 11. ..define a member function 12. ..make an outside function inline 13. ..nest member functions 14. ..employ private member functions 15. ..use arrays within a class 16. ..allocate memory for objects 17. ..employ static member functions 18. ..make arrays of objects 19. ..use objects as function arguments 20. ..use friendly functions 21. ..make functions return objects 22. ..create const member functions 23. ..know what pointers to members are

Functions Introduction to User-defined functions in C++ A function is a subprogram that acts on data and often returns a value. You are already familiar with the one function that every C++ program possesses: int main(void). Good C++ programmers write programs that consist of many of these small functions. These programmers know that a program written with numerous functions is easier to maintain, update and debug than one very long program. By programming in a modular (functional) fashion, several programmers can work independently on separate functions which can be assembled at a later date to create the entire project. Ideally, your main( ) function should be very short and should consist primarily of function calls. Each function has its own name. When that name is encountered in a program, the execution of the program branches to the body of that function. When the function is finished, execution

Page 67: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

67 [email protected]

returns to the area of the program code from which it was called, and the program continues on to the next line of code.

Local Variable ..a variable that is restricted to use within a function of a program.

void functionName(void) Our first style of function will simply perform an independent task. It will not send or receive any parameters and it will not return any values. The word void appears as the return type and

the parameters. //Example program //Screen display shown at the right //Prototyping, defining and calling a function #include<iostream.h> #include<stdlib.h> void astericks(void); //function prototype int main(void) { system("CLS"); cout<<"Heads up, function!\n"; astericks( ); //function call cout<<"Again, function!\n"; astericks( ); //function call cout<<"Job well done!\n"; return 0; //main( ) is over - ALL STOP!! } //function definition void astericks(void) { int count; // declaring LOCAL variable for(count = 1; count<=10; count++) cout<<"*"; cout<<endl; return; //return value is VOID, no return }

SCREEN DISPLAY

Page 68: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

68 [email protected]

Heads up, function! ********** Again, function! ********** Job well done! *Note: One of the important features of functions is their ability to be reused. Notice how the function astericks() was called twice from main(). The programmer did not have to duplicate the code.

C++ allows programmers to define their own functions. For example the following is a definition of a function which given the co-ordinates of a point (x,y) will return its distance from the origin.

float distance(float x, float y) // Returns the distance of (x, y) from origin { float dist; //local variable dist = sqrt(x * x + y * y); return dist; } This function has two input parameters, real values x and y, and returns the distance of the point (x,y) from the origin. In the function a local variable dist is used to temporarily hold the calculated value inside the function.

The general form of a function definition in C++ is as follows:

function-type function-name( parameter-list ) { local-definitions; function-implementation; }

• If the function returns a value then the type of that value must be specified in function-type. For the moment this could be int, float or char. If the function does not return a value then the function-type must be void.

• The function-name follows the same rules of composition as identifiers. • The parameter-list lists the formal parameters of the function together with their types. • The local-definitions are definitions of variables that are used in the function-implementation.

These variables have no meaning outside the function. • The function-implementation consists of C++ executable statements that implement the

effect of the function.

Page 69: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

69 [email protected]

Functions with no parameters

Functions with no parameters are of limited use. Usually they will not return a value but carry out some operation. For example consider the following function which skips three lines on output.

void skipthree(void) // skips three lines on output { cout << endl << endl << endl; } Note that the function-type has been given as void, this tells the compiler that this function does not return any value. Because the function does not take any parameters the parameter-list is empty, this is indicated by the void parameter-list. No local variables are required by this function and the function implementation only requires the sending of three successive end of line characters to the output stream cout. Note the introductory comment that describes what the function does. All functions should include this information as minimal comment.

Since this function does not return a value it cannot be used in an expression and is called by treating it as a statement as follows:

skipthree(); Even though there are no parameters the empty parameter list () must be inserted.

When a function is called the C++ compiler must insert appropriate instructions into the object code to arrange to pass the actual parameter values to the function code and to obtain any values returned by the function. To do this correctly the compiler must know the types of all parameters and the type of any return value. Thus before processing the call of a function it must already know how the function is defined. This can be done by defining any functions that are used in the main program before the main program, for example the function skipthree could be incorporated in a program as follows:

#include <iostream.h> void skipthree(void) // Function to skip three lines { cout << endl << endl << endl; } void main() { int ....; float ....; cout << "Title Line 1";

Page 70: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

70 [email protected]

skipthree(); cout << "Title Line 2"; . . }

However this has disadvantages, namely:

• The main program tends to convey much more information of use in understanding the program than do individual functions. So it is better if the main program comes first. However this means that the compiler meets the call of a function before it meets the definition of the function.

• If using functions from a library of functions then the main program is linked with the pre-compiled object code of the functions. Thus while compiling the main program on its own the compiler has no knowledge of the function definitions.

The way round both the problems above is to use Function prototypes. A function prototype supplies information about the return type of a function and the types of its parameters. This function prototype is then placed before the main program that uses the function. The full function definition is then placed after the main program or may be contained in a separate file that is compiled separately and linked to the main program later. The function prototype is merely a copy of the function heading. Thus the function prototype for the function skipthree is:

void skipthree(void); which would be included in the program file as follows: #include <iostream.h> void skipthree(void); // function prototype void main() { int ....; float ....; cout << "Title Line 1"; skipthree(); cout << "Title Line 2"; . . } // Now the function definition void skipthree(void) // Function to skip three lines { cout << endl << endl << endl; }

Page 71: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

71 [email protected]

In fact when using functions from the stream libraries and the mathematical libraries prototypes are required for these functions. This is handled by including the files iostream.h and math.h which, among other things, contain the function prototypes.

Using functions we can structure our programs in a more modular way, accessing all the potential that structured programming can offer to us in C++.

A function is a group of statements that is executed when it is called from some point of the program. The following is its format:

type name ( parameter1, parameter2, ...) { statement }

where:

• type is the data type specifier of the data returned by the function. • name is the identifier by which it will be possible to call the function. • parameters (as many as needed): Each parameter consists of a data type specifier

followed by an identifier, like any regular variable declaration (for example: int x) and which acts within the function as a regular local variable. They allow to pass arguments to the function when it is called. The different parameters are separated by commas.

• statements is the function's body. It is a block of statements surrounded by braces { }.

Here you have the first function example:

// function example #include <iostream> using namespace std; int addition (int a, int b) { int r; r=a+b; return (r); } int main () { int z; z = addition (5,3); cout << "The result is " << z; return 0; }The result is 8

Page 72: C++ & VISUAL C++

In order to examine this code, first of all remember something said at the beginning of this tutorial: a C++ program always begins its execution by the

We can see how the main function begins by declaring the variable we see a call to a function called between the structure of the call to the function and the declaration of the function itself some code lines above:

The parameters and arguments have a clear correspondence. Within the to addition passing two values: declared for function addition.

At the point at which the function is called passed to function addition. The value of both arguments passed in the call (to the local variables int a and int b

Function addition declares another local variablit assigns to r the result of a plus respectively, the result is 8.

The following line of code:

return (r);

finalizes function addition, and returns the control back to the function that called it in the first place (in this case, main). At this moment the program follows it regular course from the same point at which it was interrupted by the call to statement in function addition that moment had a value of 8. This value becomes the value of evaluating the function call.

VISUAL C++ PROGRAMMING

[email protected]

r to examine this code, first of all remember something said at the beginning of this tutorial: a C++ program always begins its execution by the main function. So we will begin there.

function begins by declaring the variable z of type intwe see a call to a function called addition. Paying attention we will be able to see the similarity between the structure of the call to the function and the declaration of the function itself some

ameters and arguments have a clear correspondence. Within the mainpassing two values: 5 and 3, that correspond to the int a and int b

declared for function addition.

At the point at which the function is called from within main, the control is lost by . The value of both arguments passed in the call (5int b within the function.

declares another local variable (int r), and by means of the expression plus b. Because the actual parameters passed for a

d returns the control back to the function that called it in the first ). At this moment the program follows it regular course from the same

point at which it was interrupted by the call to addition. But additionally, because the specified a value: the content of variable r (return (r);. This value becomes the value of evaluating the function call.

VISUAL C++ PROGRAMMING VC++

72

r to examine this code, first of all remember something said at the beginning of this function. So we will begin there.

int. Right after that, . Paying attention we will be able to see the similarity

between the structure of the call to the function and the declaration of the function itself some

main function we called parameters

, the control is lost by main and 5 and 3) are copied

), and by means of the expression r=a+b, a and b are 5 and 3

d returns the control back to the function that called it in the first ). At this moment the program follows it regular course from the same

. But additionally, because the return return (r);), which at

. This value becomes the value of evaluating the function call.

Page 73: C++ & VISUAL C++

So being the value returned by a function the value givevaluated, the variable z will be set to the value returned by another way, you can imagine that the call to a function (value it returns (8).

The following line of code in main is:

cout << "The result is " << z;

That, as you may already expect, produces the printing of the result on the screen.

Scope of variables

The scope of variables declared within a function or any other their own block and cannot be used outside of them. For example, in the previous example it would have been impossible to use the variables function addition. Also, it would have been impossible to use the variable addition, since this was a variable local to the function

Therefore, the scope of local variables is limited to the same block level in which they aNevertheless, we also have the possibility to declare global variables; These are visible from any point of the code, inside and outside all functions. In order to declare global variables you simply have to declare the variable outside any function or block; that means, directly in the body of the program.

And here is another example about functions:

// function example #include <iostream> using namespace std;

VISUAL C++ PROGRAMMING

[email protected]

So being the value returned by a function the value given to the function call itself when it is will be set to the value returned by addition (5, 3), that is

another way, you can imagine that the call to a function (addition (5,3)) is literally replaced by the

The following line of code in main is:

<< z;

That, as you may already expect, produces the printing of the result on the screen.

The scope of variables declared within a function or any other inner block is only their own function or their own block and cannot be used outside of them. For example, in the previous example it would have been impossible to use the variables a, b or r directly in function main since they were variables local to

. Also, it would have been impossible to use the variable z directly within function , since this was a variable local to the function main.

Therefore, the scope of local variables is limited to the same block level in which they aNevertheless, we also have the possibility to declare global variables; These are visible from any point of the code, inside and outside all functions. In order to declare global variables you simply have to declare the

nction or block; that means, directly in the body of the program.

And here is another example about functions:

VISUAL C++ PROGRAMMING VC++

73

en to the function call itself when it is , that is 8. To explain it

) is literally replaced by the

That, as you may already expect, produces the printing of the result on the screen.

inner block is only their own function or their own block and cannot be used outside of them. For example, in the previous example it would have

since they were variables local to directly within function

Therefore, the scope of local variables is limited to the same block level in which they are declared. Nevertheless, we also have the possibility to declare global variables; These are visible from any point of the code, inside and outside all functions. In order to declare global variables you simply have to declare the

nction or block; that means, directly in the body of the program.

Page 74: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

74 [email protected]

int subtraction (int a, int b) { int r; r=a-b; return (r); } int main () { int x=5, y=3, z; z = subtraction (7,2); cout << "The first result is " << z << '\n'; cout << "The second result is " << subtraction (7,2) << '\n'; cout << "The third result is " << subtraction (x,y) << '\n'; z= 4 + subtraction (x,y); cout << "The fourth result is " << z << '\n'; return 0; } The first result is 5 The second result is 5 The third result is 2 The fourth result is 6

In this case we have created a function called subtraction. The only thing that this function does is to subtract both passed parameters and to return the result.

Nevertheless, if we examine function main we will see that we have made several calls to function subtraction. We have used some different calling methods so that you see other ways or moments when a function can be called.

In order to fully understand these examples you must consider once again that a call to a function could be replaced by the value that the function call itself is going to return. For example, the first case (that you should already know because it is the same pattern that we have used in previous examples):

z = subtraction (7,2); cout << "The first result is " << z;

If we replace the function call by the value it returns (i.e., 5), we would have:

z = 5; cout << "The first result is " << z;

As well as

Page 75: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

75 [email protected]

cout << "The second result is " << subtraction (7,2);

has the same result as the previous call, but in this case we made the call to subtraction directly as an insertion parameter for cout. Simply consider that the result is the same as if we had written:

cout << "The second result is " << 5;

since 5 is the value returned by subtraction (7,2).

In the case of:

cout << "The third result is " << subtraction (x,y);

The only new thing that we introduced is that the parameters of subtraction are variables instead of constants. That is perfectly valid. In this case the values passed to function subtraction are the values of x and y, that are 5 and 3 respectively, giving 2 as result.

The fourth case is more of the same. Simply note that instead of:

z = 4 + subtraction (x,y);

we could have written:

z = subtraction (x,y) + 4;

with exactly the same result. I have switched places so you can see that the semicolon sign (;) goes at the end of the whole statement. It does not necessarily have to go right after the function call. The explanation might be once again that you imagine that a function can be replaced by its returned value:

z = 4 + 2; z = 2 + 4;

Functions with no type. The use of void.

If you remember the syntax of a function declaration:

type name ( argument1, argument2 ...) statement

you will see that the declaration begins with a type, that is the type of the function itself (i.e., the type of the datum that will be returned by the function with the return statement). But what if we want to return no value?

Page 76: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

76 [email protected]

Imagine that we want to make a function just to show a message on the screen. We do not need it to return any value. In this case we should use the void type specifier for the function. This is a special specifier that indicates absence of type.

// void function example #include <iostream> using namespace std; void printmessage () { cout << "I'm a function!"; } int main () { printmessage (); return 0; }

void can also be used in the function's parameter list to explicitly specify that we want the function to take no actual parameters when it is called. For example, function printmessage could have been declared as:

void printmessage (void) { cout << "I'm a function!";

}

Although it is optional to specify void in the parameter list. In C++, a parameter list can simply be left blank if we want a function with no parameters. What you must always remember is that the format for calling a function includes specifying its name and enclosing its parameters between parentheses. The non-existence of parameters does not exempt us from the obligation to write the parentheses. For that reason the call to printmessage is:

printmessage ();

The parentheses clearly indicate that this is a call to a function and not the name of a variable or some other C++ statement. The following call would have been incorrect:

printmessage;

Page 77: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

77 [email protected]

Functions with parameters and no return value

The function of the previous section is not very useful, what if four lines were to be skipped, or two lines? It would be much more useful if it was possible to tell the function how many lines to skip. That is the function should have an input parameter which indicates how many lines should be skipped.

The function skipthree() is now changed to the function skip which has a parameter n indicating how many lines have to be skipped as follows:

void skip(int n) // Function skips n lines on output { int i; // a local variable to this function // now loop n times for (i = 0; i < n; i++) cout << endl; }

As before this function does not return a value hence it is declared as having type void. It now takes an integer parameter n which indicates the number of lines to be skipped. The parameter list then consists of a type and a name for this formal parameter. Inside the body of the function (enclosed in {}) a loop control variable i is declared. This variable is a local variable to the function. A local variable defined within the body of the function has no meaning, or value, except within the body of the function. It can use an identifier name that is used elsewhere in the program without there being any confusion with that variable. Thus changing the value of the local variable i in the function skip will not affect the value of any other variable i used elsewhere in the program. Similarly changing the value of a variable i used elsewhere in the program will not affect the value of the local variable i in skip.

The function is called in the same manner as skipthree() above, but a value must be given for the parameter n. Thus all the following calls are acceptable:

void main() { int m = 6, n = 3; ...............; skip(m); .......; skip(m + n); ............; skip(4); .......; }

Page 78: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

78 [email protected]

however the call: skip (4.0); would not be acceptable because the actual parameter type must match the formal parameter type given in the definition of the function.

In writing the function prototype for a function with parameters it is not necessary to detail the formal names given to the parameters of the function, only their types. Thus a suitable function prototype for the parameterised version of skip would be:

void skip(int); // function prototype Functions that return values

One of the most useful forms of function is one that returns a value that is a function of its parameters. In this case the type given to the function is that of the value to be returned. Thus consider the function, previously considered, which given the co-ordinates of a point (x,y) will return its distance from the origin:

float distance(float x, float y) // Returns the distance of (x, y) from origin { float dist; //local variable dist = sqrt(x * x + y * y); return dist; }

The function prototype for this function is:

float distance(float, float); // function prototype

This function introduces several new features. Note the following:

• The function has been given the type float because it is going to return a float value. • The parameter-list now has two parameters, namely, x and y. Each parameter is declared by

giving its type and name and successive parameter declarations are separated by a comma.

• A local variable dist has been declared to temporarily hold the calculated distance. • Because this function returns a value it includes a return statement which returns the

value. In a statement return value the value may be a constant, a variable or an expression. Hence the use of the local variable dist was not essential since the return statement could have been written:

• return sqrt(x*x + y*y);

Page 79: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

79 [email protected]

When the function is called the formal parameters x and y are replaced by actual parameters of type float and in the same order, i.e. the x co-ordinate first. Since the function returns a value it can only be used in an expression.

Hence the following examples of the use of the above function in a program in which it is declared:

float a, b, c, d, x, y; a = 3.0; b = 4.4; c = 5.1; d = 2.6; x = distance(a, b); y = distance(c, d); if (distance(4.1, 6.7) > distance(x, y)) cout << "Message 1" << endl;

A function may have several return statements. This is illustrated in the following function which implements the algorithm for evaluating the square root previously considered.

float mysqrt(float x) // Function returns square root of x. // If x is negative it returns zero. { const float tol = 1.0e-7; // 7 significant figures float xold, xnew; // local variables if (x <= 0.0) return 0.0; // covers -ve and zero case else { xold = x; // x as first approx xnew = 0.5 * (xold + x / xold); // better approx while (fabs((xold-xnew)/xnew) > tol) { xold = xnew; xnew = 0.5 * (xold + x / xold); } return xnew; // must return float value } } // end mysqrt

If the function has type void then it must not return a value. If a void function does return a value then most compilers will issue some form of warning message that a return value is not expected.

Arguments passed by value and by reference.

Page 80: C++ & VISUAL C++

Until now, in all the functions we have seen, the arguments passed to the functions have been passed by value. This means that when calling a function with parameters, what we have passed to the function were copies of their valuesuppose that we called our first function

int x=5, y=3, z; z = addition ( x , y );

What we did in this case was to call to function addition passing the values of 3 respectively, but not the variables

This way, when the function addition is called, the value of its local variables and 3 respectively, but any modification to either have any effect in the values of passed to the function, but only copies of their values at the moment the function was called.

But there might be some cases where you needan external variable. For that purpose we can use arguments passed by reference, as in the function duplicate of the following example:

// passing parameters by reference#include <iostream> using namespace std; void duplicate (int& a, int& b, int& c){ a*=2; b*=2; c*=2; } int main () { int x=1, y=3, z=7; duplicate (x, y, z); cout << "x=" << x << ", y=" return 0; }

VISUAL C++ PROGRAMMING

[email protected]

Until now, in all the functions we have seen, the arguments passed to the functions have been . This means that when calling a function with parameters, what we have passed to

the function were copies of their values but never the variables themselves. For example, suppose that we called our first function addition using the following code:

What we did in this case was to call to function addition passing the values of respectively, but not the variables x and y themselves.

This way, when the function addition is called, the value of its local variables arespectively, but any modification to either a or b within the function ad

have any effect in the values of x and y outside it, because variables x and y were not themselves passed to the function, but only copies of their values at the moment the function was called.

But there might be some cases where you need to manipulate from inside a function the value of an external variable. For that purpose we can use arguments passed by reference, as in the function duplicate of the following example:

// passing parameters by reference

& c)

", y=" << y << ", z=" << z;

x=2, y=6, z=14

VISUAL C++ PROGRAMMING VC++

80

Until now, in all the functions we have seen, the arguments passed to the functions have been . This means that when calling a function with parameters, what we have passed to

s but never the variables themselves. For example,

What we did in this case was to call to function addition passing the values of x and y, i.e. 5 and

a and b become 5 within the function addition will not

were not themselves passed to the function, but only copies of their values at the moment the function was called.

to manipulate from inside a function the value of an external variable. For that purpose we can use arguments passed by reference, as in the

Page 81: C++ & VISUAL C++

The first thing that should call your aeach parameter was followed by an ampersand sign (their corresponding arguments are to be passed

When a variable is passed by reference we are not passing a copy of its value, but we are somehow passing the variable itself to the function and any modification that we do to the local variables will have an effect in their counterpart variables passed as arguments in the cafunction.

To explain it in another way, we associate call (x, y and z) and any change that we do on outside it. Any change that we do on

That is why our program's output, that shows the values stored in duplicate, shows the values of all the three variables of

If when declaring the following function:

void duplicate (int& a, int& b,

we had declared it this way:

void duplicate (int a, int b, int

i.e., without the ampersand signs (copy of their values instead, and therefore, the oubeen the values of x, y and z without having been modified.

Passing by reference is also an effective way to allow a function to return more than one value. For example, here is a function that returns the previoupassed.

// more than one returning value#include <iostream>

VISUAL C++ PROGRAMMING

[email protected]

The first thing that should call your attention is that in the declaration of duplicateeach parameter was followed by an ampersand sign (&). This ampersand is what specifies that their corresponding arguments are to be passed by reference instead of by value.

ssed by reference we are not passing a copy of its value, but we are somehow passing the variable itself to the function and any modification that we do to the local variables will have an effect in their counterpart variables passed as arguments in the ca

To explain it in another way, we associate a, b and c with the arguments passed on the function ) and any change that we do on a within the function will affect the value of

outside it. Any change that we do on b will affect y, and the same with c and z

That is why our program's output, that shows the values stored in x, y and z after the call to , shows the values of all the three variables of main doubled.

If when declaring the following function:

& b, int& c)

int c)

i.e., without the ampersand signs (&), we would have not passed the variables by reference, but a copy of their values instead, and therefore, the output on screen of our program would have

without having been modified.

Passing by reference is also an effective way to allow a function to return more than one value. For example, here is a function that returns the previous and next numbers of the first parameter

// more than one returning value

VISUAL C++ PROGRAMMING VC++

81

duplicate the type of ). This ampersand is what specifies that

ssed by reference we are not passing a copy of its value, but we are somehow passing the variable itself to the function and any modification that we do to the local variables will have an effect in their counterpart variables passed as arguments in the call to the

with the arguments passed on the function within the function will affect the value of x

z.

after the call to

), we would have not passed the variables by reference, but a tput on screen of our program would have

Passing by reference is also an effective way to allow a function to return more than one value. s and next numbers of the first parameter

Page 82: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

82 [email protected]

using namespace std; void prevnext (int x, int& prev, int& next) { prev = x-1; next = x+1; } int main () {

int x=100, y, z; prevnext (x, y, z); cout << "Previous=" << y << ", Next=" << z;

return 0; } Previous=99, Next=101

Default values in parameters.

When declaring a function we can specify a default value for each parameter. This value will be used if the corresponding argument is left blank when calling to the function. To do that, we simply have to use the assignment operator and a value for the arguments in the function declaration. If a value for that parameter is not passed when the function is called, the default value is used, but if a value is specified this default value is ignored and the passed value is used instead. For example: // default values in functions #include <iostream>

using namespace std;

int divide (int a, int b=2) {

int r; r=a/b;

return (r); }

int main () { cout << divide (12); cout << endl; cout << divide (20,4);

return 0; }

As we can see in the body of the program there are two calls to function divide. In the first one:

divide (12)

we have only specified one argument, but the function divide allows up to two. So the function divide has assumed that the second parameter is 2 since that is what we have specified to happen

Page 83: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

83 [email protected]

if this parameter was not passed (notice the function declaration, which finishes with int b=2, not just int b). Therefore the result of this function call is 6 (12/2).

In the second call:

divide (20,4)

there are two parameters, so the default value for b (int b=2) is ignored and b takes the value passed as argument, that is 4, making the result returned equal to 5 (20/4).

Example function: sum of squares of integers

The following function returns the sum of the squares of the first n integers when it is called with parameter n.

// This function returns the sum of squares of the // first n integers int sumsq(int n) { int sum = 0; int i; for (i = 1; i <= n; i++) sum += i * i; return sum; } // End of sumsq

A typical use of sumsq is: float sumsquare; int number; cout << "Enter number (>= 0): "; cin >> number; sumsquare = sumsq(number);

Example Function: Raising to the power This function returns the value of its first parameter raised to the power of its second parameter. The second parameter is an integer, but may be 0 or negative. float power(float x, int n) { float product = 1.0; int absn; int i; if ( n == 0) return 1.0; else { absn = int(fabs(n)); for (i = 1; i <= absn; i++) product *= x; if (n < 0) return 1.0 / product; else return product; } } // end of power

A typical use of the power function is shown below

Page 84: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

84 [email protected]

float x, y; int p; cout << "Enter a float and an integer: "; cin >> x >> p; y = power(x, p); y = power(x + y, 3);

Call-by-value parameters

Suppose the function power above is now amended to include the statement

n++; just before the final closing } and the following statements are executed: p = 4; y = power(x, p); cout << p;

What would be printed out for the value of p? In fact instead of the value 5 that you might expect p would still have the value 4. This is because the parameter has been passed by value.

This means that when the function is called a copy of the value of the actual parameter used in the call is passed across to the memory space of the function. Anything that happens inside the function to this copy of the value of the parameter cannot affect the original actual parameter.

All the examples that have been considered have used call-by-value parameters. This is because all the parameters used have been input parameters. To make a parameter call-by-value it is specified in the parameter list by giving its type followed by its name.

Thus if a parameter is only to be used for passing information into a function and does not have to be returned or passed back from the function then the formal parameter representing that parameter should be call-by-value. Note also that since the function cannot change the value of a call-by-value parameter in the calling program strange side effects of calling a function are avoided.

Further User-defined functions in C++

In Lesson 21 all function parameters were input-only parameters and thus were implemented as call-by value parameters. The only method used to return information to the calling program was by the function returning a single value. Frequently it is necessary to write functions that return more than one value. For example a function that took a sum of money in pence might have to return the equivalent sum in pounds and pence.

Page 85: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

85 [email protected]

To allow information to be returned to the calling program C++ allows information to be returned by parameters. As explained in Lesson 21 this cannot be done by the use of call-by-value parameters. To allow a parameter to return a value it must be declared to be a call-by-reference parameter.

Call-by-reference parameters

Values cannot be returned to the calling program via call-by-value parameters because the function only operates on a copy of the value of the parameters, not on the actual parameter itself. If it is required to return a value by a parameter then the address of the actual parameter used in the function call must be passed to the function. The function can then use this address to access the actual parameter in its own space in the calling program and change it if required. Thus what we are passing is a reference to the parameter. Hence call-by-reference parameters.

To indicate that a parameter is called by reference an & is placed after the type in the parameter list. Any change that is made to that parameter in the function body will then be reflected in its value in the calling program.

For example consider the following function to evaluate the solution of a quadratic equation:

// solves the quadratic equation a*x*x+b*x+c = 0. // If the roots are real then the roots are // returned in two parameters root1 and root2 and // the function returns true, if they are complex // then the function returns false. bool quadsolve(float a, // IN coefficient float b, // IN coefficient float c, // IN coefficient float& root1, // OUT root float& root2) // OUT root { float disc; // local variable disc = b * b - 4 * a * c; if (disc < 0.0) return false; else { root1 = (-b + sqrt(disc))/(2 * a); root2 = (-b - sqrt(disc))/(2 * a); return true; } }

Note that the roots, which are output parameters, have been declared to be reference parameters, while the coefficients are input parameters and hence are declared to be value parameters. The function prototype would have the following form:

Page 86: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

86 [email protected]

int quadsolve(float, float, float, float&, float&);

This might be called in a program as follows:

float c1, c2, c3; float r1, r2; . . if (quadsolve(c1, c2, c3, r1, r2)) cout << "Roots are " << r1 << " and " << r2 << endl; else cout << "Complex Roots" << endl;

Note how the return value has been used to discriminate between the situation where the roots are real and are found in the two output parameters and the case where the roots are complex and no values for the roots are returned.

Recursivity.

Recursivity is the property that functions have to be called by themselves. It is useful for many tasks, like sorting or calculate the factorial of numbers. For example, to obtain the factorial of a number (n!) the mathematical formula would be: n! = n * (n-1) * (n-2) * (n-3) ... * 1

more concretely, 5! (factorial of 5) would be:

5! = 5 * 4 * 3 * 2 * 1 = 120

and a recursive function to calculate this in C++ could be:

// factorial calculator #include <iostream>

using namespace std;

long factorial (long a) {

if (a > 1) return (a * factorial (a-1)); else return (1); }

int main () {

long number;

Page 87: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

87 [email protected]

cout << "Please type a number: "; cin >> number; cout << number << "! = " << factorial (number);

return 0; }

Please type a number: 9 9! = 362880

Notice how in function factorial we included a call to itself, but only if the argument passed was greater than 1, since otherwise the function would perform an infinite recursive loop in which once it arrived to 0 it would continue multiplying by all the negative numbers (probably provoking a stack overflow error on runtime).

This function has a limitation because of the data type we used in its design (long) for more simplicity. The results given will not be valid for values much greater than 10! or 15!, depending on the system you compile it.

Declaring functions.

Until now, we have defined all of the functions before the first appearance of calls to them in the source code. These calls were generally in function main which we have always left at the end of the source code. But if you try to repeat some of the examples of functions described so far, but placing the function main before any of the other functions that were called from within it, you will most likely obtain compiling errors. The reason is that to be able to call a function this must have been declared in some earlier point of the code, like we have done in all our examples.

But there is an alternative way to avoid writing the whole code of a function before it can be used in main or in some other function. This can be achieved by declaring just a prototype of the function before it is used, instead of the entire definition. This declaration is shorter than the entire definition, but significant enough for the compiler to determine its return type and the types of its parameters.

Its form is:

type name ( argument_type1, argument_type2, ...);

It is identical to a function definition, except that it does not include the body of the function itself (i.e., the function statements that in normal definitions are enclosed in braces { }) and instead of that we end the prototype declaration with a mandatory semicolon (;).

The parameter enumeration does not need to include the identifiers, but only the type specifiers. The inclusion of a name for each parameter as in the function definition is optional in the prototype declaration. For example, we can declare a function called protofunction with two int parameters with any of the following declarations:

Page 88: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

88 [email protected]

int protofunction (int first, int second); int protofunction (int, int);

Anyway, including a name for each variable makes the prototype more legible.

// declaring functions prototypes #include <iostream>

using namespace std;

void odd (int a); void even (int a);

int main () {

int i; do { cout << "Type a number: (0 to exit) "; cin >> i; odd (i);

} while (i!=0); return 0; }

void odd (int a) {

if ((a%2)!=0) cout << "Number is odd.\n";

else even (a); }

void even (int a) {

if ((a%2)==0) cout << "Number is even.\n";

else odd (a); }

Type a number (0 to exit): 9 Number is odd. Type a number (0 to exit): 6 Number is even. Type a number (0 to exit): 1030 Number is even. Type a number (0 to exit): 0 Number is even.

This example is indeed not an example of efficiency. I am sure that at this point you can already make a program with the same result, but using only half of the code lines that have been used in this example. Anyway this example illustrates how prototyping works. Moreover, in this concrete example the prototyping of at least one of the two functions is necessary in order to compile the code without errors.

Page 89: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

89 [email protected]

The first things that we see are the declaration of functions odd and even:

void odd (int a); void even (int a);

This allows these functions to be used before they are defined, for example, in main, which now is located where some people find it to be a more logical place for the start of a program: the beginning of the source code.

Anyway, the reason why this program needs at least one of the functions to be declared before it is defined is because in odd there is a call to even and in even there is a call to odd. If none of the two functions had been previously declared, a compilarion error would happen, since either odd would not not be visible from even (because it has still not been declared), or even would not be visible from odd (for the same reason).

Having the prototype of all functions together in the same place within the source code is found practical by some programmers, and this can be easily achieved by declaring all functions prototypes at the beginning of a program.

Review Questions 1. How is information supplied as input to a function? How can information be conveyed

back to the calling program? 2. What would the following function do? 3. void example(int n) 4. { 5. int i; 6. for (i=0; i<n; i++) 7. cout << '*'; 8. cout << endl; 9. }

How would you call this function in a program? How would you use this function in producing the following output on the screen? * ** *** ****

10. What would be the output from the following programs? a) void change(void) { int x; x = 1; } void main()

Page 90: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

90 [email protected]

{ int x; x = 0; change(); cout << x << endl; } b) void change(int x) { x = 1; } void main() { int x; x = 0; change(x); cout << x << endl; }

11. Write a function prototype for a function that takes two parameters of type float and returns true (1) if the first parameter is greater than the second and otherwise returns false (0).

12. Write a function prototype for a function that takes two parameters of type int and returns true if these two integers are a valid value for a sum of money in pounds and pence. If not valid then false should be returned.

13. A function named ex1 has a local variable named i and another function ex2 has a local variable named i. These two functions are used together with a main program which has a variable named i. Assuming that there are no other errors in the program will this program compile correctly? Will it execute correctly without any run-time errors?

Exercises 1. Write a function which draws a line of n asterisks, n being passed as a parameter to the

function. Write a driver program (a program that calls and tests the function) which uses

the function to output an m n block of asterisks, m and n entered by the user. 2. Extend the function of the previous exercise so that it prints a line of n asterisks starting

in column m. It should take two parameters m and n. If the values of m and n are such that the line of asterisks would extend beyond column 80 then the function should return false and print nothing, otherwise it should output true and print the line of asterisks. Amend your driver program so that it uses the function return value to terminate execution with an error message if m and n are such that there would be line overflow.

Think carefully about the test data you would use to test the function.

3. Write a function which converts a sum of money given as an integer number of pence into a floating point value representing the equivalent number of pounds. For example 365 pence would be 3.65 pounds.

Page 91: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

91 [email protected]

Overloaded functions.

In C++ two different functions can have the same name if their parameter types or number are different. That means that you can give the same name to more than one function if they have either a different number of parameters or different types in their parameters. For example: // overloaded function #include <iostream>

using namespace std;

int operate (int a, int b) {

return (a*b); }

float operate (float a, float b) {

return (a/b); }

int main () { int x=5,y=2; float n=5.0,m=2.0; cout << operate (x,y); cout << "\n"; cout << operate (n,m); cout << "\n"; return 0; }

In this case we have defined two functions with the same name, operate, but one of them accepts two parameters of type int and the other one accepts them of type float. The compiler knows which one to call in each case by examining the types passed as arguments when the function is called. If it is called with two ints as its arguments it calls to the function that has two int parameters in its prototype and if it is called with two floats it will call to the one which has

two float parameters in its prototype.

In the first call to operate the two arguments passed are of type int, therefore, the function with the first prototype is called; This function returns the result of multiplying both parameters.

While the second call passes two arguments of type float, so the function with the second prototype is called. This one has a different behavior: it divides one parameter by the other. So the behavior of a call to operate depends on the type of the arguments passed because the function has been overloaded.

Page 92: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

92 [email protected]

Notice that a function cannot be overloaded only by its return type. At least one of its parameters must have a different type.

inline functions.

The inline specifier is an optimization specifier. It does not change the behavior of a function, but serves to indicate to the compiler that the code the function body generates shall be inserted at the point of each call to the function, instead of doing a regular call that generally involves stacking variables and jumping to other memory locations. This is equivalent to declaring a macro. It only represents an overhead advantage for very short functions, in which the resulting code from compiling the program may be faster when the overhead required to call a function is avoided.

The format for its declaration is:

inline type name ( arguments ... ) { instructions ... }

and the call is just like the call to any other function. You do not have to include the inline keyword when calling the function, only in its declaration.

Most compilers already optimize code to generate inline functions when it is more convenient. This specifier only indicates to the compiler that inline is preferred for this function.

C++ Virtual Function - Properties:

C++ virtual function is,

• A member function of a class • Declared with virtual keyword • Usually has a different functionality in the derived class • A function call is resolved at run-time

The difference between a non-virtual c++ member function and a virtual member function is, the non-virtual member functions are resolved at compile time. This mechanism is called static binding. Where as the c++ virtual member functions are resolved during run-time. This mechanism is known as dynamic binding.

C++ Virtual Function - Reasons:

The most prominent reason why a C++ virtual function will be used is to have a different functionality in the derived class.

Page 93: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

93 [email protected]

For example a Create function in a class Window may have to create a window with white background. But a class called CommandButton derived or inherited from Window, may have to use a gray background and write a caption on the center. The Create function for CommandButton now should have a functionality different from the one at the class called Window.

C++ Virtual function - Example:

This article assumes a base class named Window with a virtual member function named Create. The derived class name will be CommandButton, with our over ridden function Create.

class Window // Base class for C++ virtual function example { public: virtual void Create() // virtual function for C++ virtual function example { cout <<"Base class Window"<<endl; } };

class CommandButton : public Window { public: void Create() { cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl; } }; void main() { Window *x, *y; x = new Window(); x->Create(); y = new CommandButton(); y->Create(); } The output of the above program will be, Base class Window Derived class Command Button

If the function had not been declared virtual, then the base class function would have been called all the times. Because, the function address would have been statically bound during

Page 94: C++ & VISUAL C++

compile time. But now, as the function is declared virtual it is a candidate for runand the derived class function is being invoked.

C++ Virtual function - Call Mechanism:

Whenever a program has a C++ virtual function declared, a vThe v-table consists of addresses to the virtual functions for classes and pointers to the functions from each of the objects of the derived class. Whenever there is a function call madvirtual function, the v-table is used to resolve to the function address. This is how the Dynamic binding happens during a virtual function call.

Arrays

An array is a series of elements of the same type placed in contiguous memory locations tbe individually referenced by adding an index to a unique identifier.

That means that, for example, we can store 5 values of type declare 5 different variables, each one with a different identifier. Instead of thawe can store 5 different values of the same type,

For example, an array to contain 5 integer values of type this:

where each blank panel represents type int. These elements are numbered from independently of its length.

Like a regular variable, an array must be declared before it is uarray in C++ is:

type name [elements];

where type is a valid type (like intis always enclosed in square brackets contain.

VISUAL C++ PROGRAMMING

[email protected]

compile time. But now, as the function is declared virtual it is a candidate for runand the derived class function is being invoked.

Call Mechanism:

C++ virtual function declared, a v-table is constructed for the class. table consists of addresses to the virtual functions for classes and pointers to the functions

from each of the objects of the derived class. Whenever there is a function call madtable is used to resolve to the function address. This is how the Dynamic

binding happens during a virtual function call.

An array is a series of elements of the same type placed in contiguous memory locations tbe individually referenced by adding an index to a unique identifier.

That means that, for example, we can store 5 values of type int in an array without having to declare 5 different variables, each one with a different identifier. Instead of thawe can store 5 different values of the same type, int for example, with a unique identifier.

For example, an array to contain 5 integer values of type int called billy could be represented like

where each blank panel represents an element of the array, that in this case are integer values of . These elements are numbered from 0 to 4 since in arrays the first index is always

Like a regular variable, an array must be declared before it is used. A typical declaration for an

int, float...), name is a valid identifier and the elementsis always enclosed in square brackets []), specifies how many of these elements the array has to

VISUAL C++ PROGRAMMING VC++

94

compile time. But now, as the function is declared virtual it is a candidate for run-time linking

table is constructed for the class. table consists of addresses to the virtual functions for classes and pointers to the functions

from each of the objects of the derived class. Whenever there is a function call made to the c++ table is used to resolve to the function address. This is how the Dynamic

An array is a series of elements of the same type placed in contiguous memory locations that can

in an array without having to declare 5 different variables, each one with a different identifier. Instead of that, using an array

for example, with a unique identifier.

could be represented like

an element of the array, that in this case are integer values of since in arrays the first index is always 0,

sed. A typical declaration for an

elements field (which nts the array has to

Page 95: C++ & VISUAL C++

Therefore, in order to declare an array called simple as:

int billy [5];

NOTE: The elements field within brackets is going to hold, must be a constantwhose size must be determined before execution. In order to create arrays with a variable length dynamic memory is needed, which is explained later in these tutorials.

Initializing arrays.

When declaring a regular array of local scope (within a function, for example), if we do not specify otherwise, its elements will not be initialized to any value by default, so their content will be undetermined until we store some vthe other hand, are automatically initialized with their default values, which for all fundamental types this means they are filled with zeros.

In both cases, local and global, when we declare anvalues to each one of its elements by enclosing the values in braces

int billy [5] = { 16, 2, 77, 40, 12071 };

This declaration would have created an array like this:

The amount of values between braces we declare for the array between square brackets we have declared that it has 5 elements and in the list of initial values within specified 5 values, one for each element.

When an initialization of values is provided for an array, C++ allows the possibility of leaving the square brackets empty [ ]. In this case, the compiler will assume a size for the array that matches the number of values included between braces

int billy [] = { 16, 2, 77, 40, 12071 };

VISUAL C++ PROGRAMMING

[email protected]

Therefore, in order to declare an array called billy as the one shown in the above diagram it is as

field within brackets [] which represents the number of elements the array constant value, since arrays are blocks of non-dynamic memory

whose size must be determined before execution. In order to create arrays with a variable length dynamic memory is needed, which is explained later in these tutorials.

When declaring a regular array of local scope (within a function, for example), if we do not specify otherwise, its elements will not be initialized to any value by default, so their content will be undetermined until we store some value in them. The elements of global and static arrays, on the other hand, are automatically initialized with their default values, which for all fundamental types this means they are filled with zeros.

In both cases, local and global, when we declare an array, we have the possibility to assign initial values to each one of its elements by enclosing the values in braces { }. For example:

billy [5] = { 16, 2, 77, 40, 12071 };

This declaration would have created an array like this:

values between braces { } must not be larger than the number of elements that we declare for the array between square brackets [ ]. For example, in the example of array we have declared that it has 5 elements and in the list of initial values within braces specified 5 values, one for each element.

When an initialization of values is provided for an array, C++ allows the possibility of leaving . In this case, the compiler will assume a size for the array that

matches the number of values included between braces { }:

billy [] = { 16, 2, 77, 40, 12071 };

VISUAL C++ PROGRAMMING VC++

95

as the one shown in the above diagram it is as

which represents the number of elements the array dynamic memory

whose size must be determined before execution. In order to create arrays with a variable length

When declaring a regular array of local scope (within a function, for example), if we do not specify otherwise, its elements will not be initialized to any value by default, so their content will

alue in them. The elements of global and static arrays, on the other hand, are automatically initialized with their default values, which for all fundamental

array, we have the possibility to assign initial . For example:

must not be larger than the number of elements that . For example, in the example of array billy

braces { } we have

When an initialization of values is provided for an array, C++ allows the possibility of leaving . In this case, the compiler will assume a size for the array that

Page 96: C++ & VISUAL C++

After this declaration, array billyvalues.

Accessing the values of an array.

In any point of a program in which an array is visible, we can access the value of any of its elements individually as if it was a normal variable, thus being able to both read and modify its value. The format is as simple as:

name[index]

Following the previous examples in which of type int, the name which we can use to refer to each element is the following:

For example, to store the value statement:

billy[2] = 75;

and, for example, to pass the value of the third element of write:

a = billy[2];

Therefore, the expression billy[2]

Notice that the third element oone is billy[1], and therefore, the third one is billy[4]. Therefore, if we write billy[5], we would be accessing the sixth elementherefore exceeding the size of the array.

In C++ it is syntactically correct to exceed the valid range of indices for an array. This can create problems, since accessing out-ofruntime errors. The reason why this is allowed will be seen further ahead when we begin to use pointers.

VISUAL C++ PROGRAMMING

[email protected]

billy would be 5 ints long, since we have provided 5 initialization

Accessing the values of an array.

of a program in which an array is visible, we can access the value of any of its elements individually as if it was a normal variable, thus being able to both read and modify its value. The format is as simple as:

ples in which billy had 5 elements and each of those elements was , the name which we can use to refer to each element is the following:

For example, to store the value 75 in the third element of billy, we could write the following

and, for example, to pass the value of the third element of billy to a variable called

billy[2] is for all purposes like a variable of type int.

Notice that the third element of billy is specified billy[2], since the first one is , and therefore, the third one is billy[2]. By this same reason, its last element is

. Therefore, if we write billy[5], we would be accessing the sixth elementherefore exceeding the size of the array.

In C++ it is syntactically correct to exceed the valid range of indices for an array. This can create of-range elements do not cause compilation errors but can cause

runtime errors. The reason why this is allowed will be seen further ahead when we begin to use

VISUAL C++ PROGRAMMING VC++

96

would be 5 ints long, since we have provided 5 initialization

of a program in which an array is visible, we can access the value of any of its elements individually as if it was a normal variable, thus being able to both read and modify its

had 5 elements and each of those elements was , the name which we can use to refer to each element is the following:

, we could write the following

to a variable called a, we could

.

, since the first one is billy[0], the second . By this same reason, its last element is

. Therefore, if we write billy[5], we would be accessing the sixth element of billy and

In C++ it is syntactically correct to exceed the valid range of indices for an array. This can create range elements do not cause compilation errors but can cause

runtime errors. The reason why this is allowed will be seen further ahead when we begin to use

Page 97: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

97 [email protected]

At this point it is important to be able to clearly distinguish between the two uses that brackets [ ] have related to arrays. They perform two different tasks: one is to specify the size of arrays when they are declared; and the second one is to specify indices for concrete array elements. Do not confuse these two possible uses of brackets [ ] with arrays.

int billy[5]; // declaration of a new array billy[2] = 75; // access to an element of the array.

If you read carefully, you will see that a type specifier always precedes a variable or array declaration, while it never precedes an access.

Some other valid operations with arrays:

billy[0] = a; billy[a] = 75; b = billy [a+2]; billy[billy[a]] = billy[2] + 5;

// arrays example #include <iostream> using namespace std; int billy [] = {16, 2, 77, 40, 12071}; int n, result=0; int main () { for ( n=0 ; n<5 ; n++ ) { result += billy[n]; } cout << result; return 0; } 12206

Multidimensional arrays

Multidimensional arrays can be described as "arrays of arrays". For example, a bidimensional array can be imagined as a bidimensional table made of elements, all of them of a same uniform data type.

Page 98: C++ & VISUAL C++

jimmy represents a bidimensional array of 3 per 5 elements of type array in C++ would be:

int jimmy [3][5];

and, for example, the way to reference the second element vertically and fourth horizontally in an expression would be:

jimmy[1][3]

(remember that array indices always begin by zero).

Multidimensional arrays are not limited to two indices (i.e., two dimensions). They can contain as many indices as needed. But be careful! The amount of memory needincreases with each dimension. For example:

char century [100][365][24][60][60];

declares an array with a char element for each second in a century, that is more than 3 billion chars. So this declaration would consume more than 3 g

Multidimensional arrays are just an abstraction for programmers, since we can obtain the same results with a simple array just by putting a factor between its indices:

int jimmy [3][5]; // is equivalent toint jimmy [15]; // (3 * 5 = 15)

With the only difference that with multidimensional arrays the compiler remembers the depth of each imaginary dimension for us. Take as example these two pieces of code, with both exactly the same result. One uses a bidimensional array and the

VISUAL C++ PROGRAMMING

[email protected]

represents a bidimensional array of 3 per 5 elements of type int. The way to declare this

and, for example, the way to reference the second element vertically and fourth horizontally in

(remember that array indices always begin by zero).

Multidimensional arrays are not limited to two indices (i.e., two dimensions). They can contain as many indices as needed. But be careful! The amount of memory needed for an array rapidly increases with each dimension. For example:

century [100][365][24][60][60];

element for each second in a century, that is more than 3 billion chars. So this declaration would consume more than 3 gigabytes of memory!

Multidimensional arrays are just an abstraction for programmers, since we can obtain the same results with a simple array just by putting a factor between its indices:

// is equivalent to * 5 = 15)

With the only difference that with multidimensional arrays the compiler remembers the depth of each imaginary dimension for us. Take as example these two pieces of code, with both exactly the same result. One uses a bidimensional array and the other one uses a simple array:

VISUAL C++ PROGRAMMING VC++

98

. The way to declare this

and, for example, the way to reference the second element vertically and fourth horizontally in

Multidimensional arrays are not limited to two indices (i.e., two dimensions). They can contain as ed for an array rapidly

element for each second in a century, that is more than 3 billion

Multidimensional arrays are just an abstraction for programmers, since we can obtain the same

With the only difference that with multidimensional arrays the compiler remembers the depth of each imaginary dimension for us. Take as example these two pieces of code, with both exactly

other one uses a simple array:

Page 99: C++ & VISUAL C++

multidimensional array

#define WIDTH 5 #define HEIGHT 3 int jimmy [HEIGHT][WIDTH];int n,m; int main () { for (n=0;n<HEIGHT;n++) for (m=0;m<WIDTH;m++) { jimmy[n][m]=(n+1)*(m+1); } return 0; }

None of the two source codes aboto the memory block called jimmy in the following way:

We have used "defined constants" (program. For example, in case that we decided could be done simply by changing the line:

#define HEIGHT 3

to:

#define HEIGHT 4

with no need to make any other modifications to the program.

Arrays as parameters

At some moment we may need to pass possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address. In practice this has almost the same effect and it is a much faster and more efficient operation.

VISUAL C++ PROGRAMMING

[email protected]

pseudo-multidimensional array

int jimmy [HEIGHT][WIDTH];

#define WIDTH 5 #define HEIGHT 3 int jimmy [HEIGHT * WIDTH]; int n,m; int main () { for (n=0;n<HEIGHT;n++) for (m=0;m<WIDTH;m++) { jimmy[n*WIDTH+m]=(n+1)*(m+1); } return 0; }

None of the two source codes above produce any output on the screen, but both assign values to the memory block called jimmy in the following way:

We have used "defined constants" (#define) to simplify possible future modifications of the program. For example, in case that we decided to enlarge the array to a height of 4 instead of 3 it could be done simply by changing the line:

with no need to make any other modifications to the program.

At some moment we may need to pass an array to a function as a parameter. In C++ it is not possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address. In practice this has almost the same effect and it is a much faster and

VISUAL C++ PROGRAMMING VC++

99

ve produce any output on the screen, but both assign values

) to simplify possible future modifications of the to enlarge the array to a height of 4 instead of 3 it

an array to a function as a parameter. In C++ it is not possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address. In practice this has almost the same effect and it is a much faster and

Page 100: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

100 [email protected]

In order to accept arrays as parameters the only thing that we have to do when declaring the function is to specify in its parameters the element type of the array, an identifier and a pair of void brackets []. For example, the following function:

void procedure (int arg[])

accepts a parameter of type "array of int" called arg. In order to pass to this function an array declared as:

int myarray [40];

it would be enough to write a call like this:

procedure (myarray);

Here you have a complete example:

// arrays as parameters #include <iostream> using namespace std; void printarray (int arg[], int length) { for (int n=0; n<length; n++) cout << arg[n] << " "; cout << "\n"; } int main () { int firstarray[] = {5, 10, 15}; int secondarray[] = {2, 4, 6, 8, 10}; printarray (firstarray,3); printarray (secondarray,5); return 0; } 5 10 15 2 4 6 8 10

As you can see, the first parameter (int arg[]) accepts any array whose elements are of type int, whatever its length. For that reason we have included a second parameter that tells the function the length of each array that we pass to it as its first parameter. This allows the for loop that prints out the array to know the range to iterate in the passed array without going out of range.

In a function declaration it is also possible to include multidimensional arrays. The format for a tridimensional array parameter is:

Page 101: C++ & VISUAL C++

base_type[][depth][depth]

for example, a function with a multidimensional array as argument could be:

void procedure (int myarray[][3][4])

Notice that the first brackets [] the compiler must be able to determine within the function which is the depth of each additional dimension.

Arrays, both simple or multidimensional, passed as function parameters are a quite common source of errors for novice programmers. I recommend the reading of the chapter about Pointers for a better understanding on how arrays operate.

Character Sequences

As you may already know, the C++ Standard Library implements a powerful is very useful to handle and manipulate strings of characters. However, because strings are in fact sequences of characters, we can represent them also as plain arrays of

For example, the following array:

char jenny [20];

is an array that can store up to 20 elements of type

Therefore, in this array, in theory, we can store sequBut we can also store shorter sequences. For example, program either the sequence "Hello"than 20 characters.

VISUAL C++ PROGRAMMING

[email protected]

base_type[][depth][depth]

for example, a function with a multidimensional array as argument could be:

myarray[][3][4])

are left blank while the following ones are not. This is so because the compiler must be able to determine within the function which is the depth of each additional

simple or multidimensional, passed as function parameters are a quite common source of errors for novice programmers. I recommend the reading of the chapter about Pointers for a better understanding on how arrays operate.

already know, the C++ Standard Library implements a powerful is very useful to handle and manipulate strings of characters. However, because strings are in fact

can represent them also as plain arrays of char elements.

For example, the following array:

is an array that can store up to 20 elements of type char. It can be represented as:

Therefore, in this array, in theory, we can store sequences of characters up to 20 characters long. But we can also store shorter sequences. For example, jenny could store at some point in a

"Hello" or the sequence "Merry christmas", since both are shorter

VISUAL C++ PROGRAMMING VC++

101

are left blank while the following ones are not. This is so because the compiler must be able to determine within the function which is the depth of each additional

simple or multidimensional, passed as function parameters are a quite common source of errors for novice programmers. I recommend the reading of the chapter about

already know, the C++ Standard Library implements a powerful string class, which is very useful to handle and manipulate strings of characters. However, because strings are in fact

elements.

. It can be represented as:

ences of characters up to 20 characters long. could store at some point in a

, since both are shorter

Page 102: C++ & VISUAL C++

Therefore, since the array of characters can store shorter sequences than its total length, a special character is used to signal the end of the valid sequence: the can be written as '\0' (backslash, zero).

Our array of 20 elements of type sequences "Hello" and "Merry Christmas"

Notice how after the valid content a null character (the end of the sequence. The panels in gray color represent values.

Initialization of null-terminated character sequences

Because arrays of characters are ordinary arrays they follow all their same rules. For example, if we want to initialize an array of characters with some predetermined sequence of characters we can do it just like any other array:

char myword[] = { 'H', 'e'

In this case we would have declared an array of 6 elements of type characters that form the word "Hello"But arrays of char elements have an additional method to initialize their values: using string literals.

In the expressions we have used in some examples in previous chapters, conentire strings of characters have already showed up several times. These are specified enclosing the text to become a string literal between double quotes ("). For example:

"the result is: "

is a constant string literal that we have

VISUAL C++ PROGRAMMING

[email protected]

refore, since the array of characters can store shorter sequences than its total length, a special character is used to signal the end of the valid sequence: the null character, whose literal constant

(backslash, zero).

f 20 elements of type char, called jenny, can be represented storing the characters "Merry Christmas" as:

Notice how after the valid content a null character ('\0') has been included in order to indicate he panels in gray color represent char elements with undetermined

terminated character sequences

Because arrays of characters are ordinary arrays they follow all their same rules. For example, if array of characters with some predetermined sequence of characters we

can do it just like any other array: 'e', 'l', 'l', 'o', '\0' };

In this case we would have declared an array of 6 elements of type char initialized with the "Hello" plus a null character '\0' at the end.

elements have an additional method to initialize their values: using string

In the expressions we have used in some examples in previous chapters, constants that represent entire strings of characters have already showed up several times. These are specified enclosing the text to become a string literal between double quotes ("). For example:

is a constant string literal that we have probably used already.

VISUAL C++ PROGRAMMING VC++

102

refore, since the array of characters can store shorter sequences than its total length, a special , whose literal constant

, can be represented storing the characters

) has been included in order to indicate elements with undetermined

Because arrays of characters are ordinary arrays they follow all their same rules. For example, if array of characters with some predetermined sequence of characters we

initialized with the

elements have an additional method to initialize their values: using string

stants that represent entire strings of characters have already showed up several times. These are specified enclosing

Page 103: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

103 [email protected]

Double quoted strings (") are literal constants whose type is in fact a null-terminated array of characters. So string literals enclosed between double quotes always have a null character ('\0') automatically appended at the end.

Therefore we can initialize the array of char elements called myword with a null-terminated sequence of characters by either one of these two methods:

char myword [] = { 'H', 'e', 'l', 'l', 'o', '\0' }; char myword [] = "Hello";

In both cases the array of characters myword is declared with a size of 6 elements of type char: the 5 characters that compose the word "Hello" plus a final null character ('\0') which specifies the end of the sequence and that, in the second case, when using double quotes (") it is appended automatically.

Please notice that we are talking about initializing an array of characters in the moment it is being declared, and not about assigning values to them once they have already been declared. In fact because this type of null-terminated arrays of characters are regular arrays we have the same restrictions that we have with any other array, so we are not able to copy blocks of data with an assignment operation.

Assuming mytext is a char[] variable, expressions within a source code like:

mystext = "Hello"; mystext[] = "Hello";

would not be valid, like neither would be:

mystext = { 'H', 'e', 'l', 'l', 'o', '\0' };

The reason for this may become more comprehensible once you know a bit more about pointers, since then it will be clarified that an array is in fact a constant pointer pointing to a block of memory.

Page 104: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

104 [email protected]

Using null-terminated sequences of characters

Null-terminated sequences of characters are the natural way of treating strings in C++, so they can be used as such in many procedures. In fact, regular string literals have this type (char[]) and can also be used in most cases.

For example, cin and cout support null-terminated sequences as valid containers for sequences of characters, so they can be used directly to extract strings of characters from cin or to insert them into cout. For example:

// null-terminated sequences of characters #include <iostream> using namespace std; int main () { char question[] = "Please, enter your first name: "; char greeting[] = "Hello, "; char yourname [80]; cout << question; cin >> yourname; cout << greeting << yourname << "!"; return 0; } Please, enter your first name: John Hello, John!

As you can see, we have declared three arrays of char elements. The first two were initialized with string literal constants, while the third one was left uninitialized. In any case, we have to speficify the size of the array: in the first two (question and greeting) the size was implicitly defined by the length of the literal constant they were initialized to. While for yourname we have explicitly specified that it has a size of 80 chars.

Finally, sequences of characters stored in char arrays can easily be converted into string objects just by using the assignment operator:

string mystring; char myntcs[]="some text"; mystring = myntcs;

Page 105: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

105 [email protected]

Bubble Sort The bubble sort gets its name because as elements are sorted they gradually "bubble" (or rise) to their proper positions, like bubbles rising in a glass of soda. The bubble sort repeatedly compares adjacent elements of an array, starting with the first and second elements, and swapping them if they are out of order. After the first and second elements are compared, the second and third elements are compared, and swapped if they are out of order. This process continues until the end of the list is reached.

When the end is reached, the bubble sort returns to elements one and two and starts the process all over again. So, when does it stop? The bubble sort knows that it is finished when it examines the entire array and no "swaps" are needed (thus the list is in proper order). The bubble sort keeps track of the occurrence of swaps by the use of a flag. The table below follows an array of numbers before, during, and after a bubble sort for descending order. A "pass" is defined as one full trip through the array comparing and if necessary, swapping, adjacent elements. Several passes have to be made through the array before it is finally sorted. Array at beginning: 84 69 76 86 94 91 After Pass #1: 84 76 86 94 91 69 After Pass #2: 84 86 94 91 76 69 After Pass #3: 86 94 91 84 76 69 After Pass #4: 94 91 86 84 76 69 After Pass #5 (done): 94 91 86 84 76 69 The bubble sort is an easy algorithm to program, but it is slower than many other sorts. With a bubble sort, it is always necessary to make one final "pass" through the array to check to see that no swaps are made to ensure that the process is finished. In actuality, the process is finished before this last pass is made. // Bubble Sort Function for Descending Order void bubble_sort(apvector <int> &array) { int i, j, flag = 1; // set flag to 1 to begin initial pass int temp; // holding variable int arrayLength = array.length( ); for(i = 1; (i <= arrayLength) && flag; i++) { flag = 0; for (j=0; j < (arrayLength -1); j++) { if (array[j+1] > array[j]) // ascending order simply changes to < { temp = array[j]; // swap elements array[j] = array[j+1]; array[j+1] = temp; flag = 1; // indicates that a swap occurred. }

Page 106: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

106 [email protected]

} } return; //arrays are passed to functions by address; nothing is returned }

Selection Sort The selection sort is a combination of searching and sorting. During each pass, the unsorted element with the smallest (or largest) value is moved to its proper position in the array. The number of times the sort passes through the array is one less than the number of items in the array. In the selection sort, the inner loop finds the next smallest (or largest) value and the outer loop places that value into its proper location. Let's look at our same table of elements using a selection sort for descending order. Remember, a "pass" is defined as one full trip through the array comparing and if necessary, swapping elements. Array at beginning: 84 69 76 86 94 91 After Pass #1: 84 91 76 86 94 69 After Pass #2: 84 91 94 86 76 69 After Pass #3: 86 91 94 84 76 69 After Pass #4: 94 91 86 84 76 69 After Pass #5 (done): 94 91 86 84 76 69

While being an easy sort to program, the selection sort is one of the least efficient. The algorithm offers no way to end the sort early, even if it begins with an already sorted list.

// Selection Sort Function for Descending Order void selection_sort(apvector <int> &array) { int i, j, first, temp; int array_size = array.length( ); for (i= array_size - 1; i > 0; i--) { first = 0; // initialize first to the subscript of the first element for (j=1; j<=i; j++) //Find smallest element between the positions 1 and i. { if (array[j] < array[first]) first = j; } temp = array[first]; // Swap smallest element found with one in position i. array[first] = array[i]; array[i] = temp; } return; } Sequential Search (Page 2 of 4 )

Page 107: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

107 [email protected]

The sequential search is best used if the array you are searching is unsorted. This method of searching is usually used on small arrays of less than 16 elements. We start the sequential search by first declaring a target to be found. The search initiates at the beginning of the array until it finds the target. In the following example we will find a target value of 23 within a one dimensional array. At index 0, 32 is not equal to 23 so we proceed on to the next element.

a[0] a[1] a[2] a[3] a[4]

32 431 -34 23 12

At index 1, 431 is not equal to 23 so we proceed.

a[0] a[1] a[2] a[3] a[4]

32 431 -34 23 12

At index 2, -34 is not equal to 23 so we proceed.

a[0] a[1] a[2] a[3] a[4]

32 431 -34 23 12

Finally at index 3, 23 is equal to 23 and we have found our target.

a[0] a[1] a[2] a[3] a[4]

32 431 -34 23 12

Now we will implement this example of a sequential search into C++ code. The program below asks the user for a target to be found, then uses a for loop to analyze each element of the array. If the array element is equal to the target it will display that the target was found. Whenever a target is found the variable “flag” will be incremented by 1. At the end of the program if the variable “flag” is less than one, then the target was obviously not found. #include <iostream> using namespace std; int main() { const int arraySize = 5; double target; int array[arraySize] = {32, 431, -34, 23, 12}; int flag; // flag is used to log how many times the target is encountered. flag = 0; cout << "Enter a target to be found: "; cin >> target; for(int cntr = 0; cntr < arraySize; cntr++) { if(array[cntr] == target) { cout << "Target found in array index " << cntr << "." << endl; flag += 1; } } // Test to see if target was found. if(flag < 1) {

Page 108: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

108 [email protected]

cout << "Target not found." << endl; } return 0; } The sequential search does have a pitfall. It is very slow and its performance rating is low. If a person had an array of one million elements, that would mean there could be up to one million comparisons, and that takes time! The sequential search method would be advisable to use only if the array you were searching was unsorted and small.

Page 109: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

109 [email protected]

Unit 5: Constructors and distractors (10 HOURS) THEORY

At the end of the unit the student should be able to:

1. ..use constructors

2. ..use parameterised constructors

3. ..use multiple constructors in a class

4. ..use constructors with default arguments

5. ..use dynamic initialisation of objects

6. ..copy constructor

7. ..use dynamic constructors

8. ..construct a two-dimensional array

9. ..use distracters

The definition and use of constructors and destructors is fairly simple. First, I'll outline some

basic rules on constructors and destructors, and then provide the details using some simple

examples.

• A constructor is a method that has the same name as its class.

• A destructor is a method that has as its name the class name prefixed by a tilde, ~.

• Neither constructors nor destructors return values. They have no return type specified.

• Constructors can have arguments.

• Constructors can be overloaded.

• If any constructor is written for the class, the compiler will not generate a default

constructor.

• The default constructor is a constructor with no arguments, or a constructor that

provides defaults for all arguments.

• The container classes such as vector require default constructors to be available for

the classes they hold. Dynamically allocated class arrays also require a default

constructor. If any constructors are defined, you should always define a default

constructor as well.

• Destructors have no arguments and thus cannot be overloaded.

Constructors and Destructors Overview

Page 110: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

110 [email protected]

Because classes have complicated internal structures, including data and functions, object

initialization and cleanup for classes is much more complicated than it is for simple data

structures. Constructors and destructors are special member functions of classes that are used

to construct and destroy class objects. Construction may involve memory allocation and

initialization for objects. Destruction may involve cleanup and deallocation of memory for

objects.

Like other member functions, constructors and destructors are declared within a class

declaration. They can be defined inline or external to the class declaration. Constructors can

have default arguments. Unlike other member functions, constructors can have member

initialization lists. The following restrictions apply to constructors and destructors:

• Constructors and destructors do not have return types nor can they return values.

• References and pointers cannot be used on constructors and destructors because their

addresses cannot be taken.

• Constructors cannot be declared with the keyword virtual.

• Constructors and destructors cannot be declared static, const, or volatile.

• Unions cannot contain class objects that have constructors or destructors.

Constructors and destructors obey the same access rules as member functions. For example,

if you declare a constructor with protected access, only derived classes and friends can use it

to create class objects.

The compiler automatically calls constructors when defining class objects and calls

destructors when class objects go out of scope. A constructor does not allocate memory for

the class object its this pointer refers to, but may allocate storage for more objects than its

class object refers to. If memory allocation is required for objects, constructors can explicitly

call the new operator. During cleanup, a destructor may release objects allocated by the

corresponding constructor. To release objects, use the delete operator.

Derived classes do not inherit constructors or destructors from their base classes, but they do

call the constructor and destructor of base classes. Destructors can be declared with the

keyword virtual.

Constructors are also called when local or temporary class objects are created, and destructors

are called when local or temporary objects go out of scope.

You can call member functions from constructors or destructors. You can call a virtual

function, either directly or indirectly, from a constructor or destructor of a class A. In this

case, the function called is the one defined in A or a base class of A, but not a function

overridden in any class derived from A. This avoids the possibility of accessing an

unconstructed object from a constructor or destructor. The following example demonstrates

this:

#include <iostream>

using namespace std;

struct A {

virtual void f() { cout << "void A::f()" << endl; }

virtual void g() { cout << "void A::g()" << endl; }

virtual void h() { cout << "void A::h()" << endl; }

Page 111: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

111 [email protected]

};

struct B : A {

virtual void f() { cout << "void B::f()" << endl; }

B() {

f();

g();

h();

}

};

struct C : B {

virtual void f() { cout << "void C::f()" << endl; }

virtual void g() { cout << "void C::g()" << endl; }

virtual void h() { cout << "void C::h()" << endl; }

};

int main() {

C obj;

}

The following is the output of the above example:

void B::f()

void A::g()

void A::h()

The constructor of B does not call any of the functions overridden in C because C has been

derived from B, although the example creates an object of type C named obj.

Copy Constructors A copy constructor is a special constructor that takes as its argument a reference to an object

of the same class and creates a new object that is a copy. By default, the compiler provides a

copy constructor that performs a member-by-member copy from the original object to the one

being created. This is called a member wise or shallow copy. Although it may seem to be the

desired behavior, in many cases a shallow copy is not satisfactory. To see why let's look at

the Employee class introduced in an earlier lesson with one change. We will store the name

in a C-style character string rather than store the employee name using the string class from

the standard C++ library. Here is a simple program with a bare bones version of the

Employee class.

#include <iostream>

using namespace std;

class Employee {

public:

Employee(char *name, int id);

~Employee();

char *getName(){return _name;}

//Other Accessor methods

private:

int _id;

char *_name;

Page 112: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

112 [email protected]

};

Employee::Employee(char *name, int id)

{

_id = id;

_name = new char[strlen(name) + 1];

//Allocates an character array object

strcpy(_name, name);

}

Employee::~Employee()

{

delete[] _name;

}

int main()

{

Employee programmer("John",22);

cout << programmer.getName() << endl;

return 0;

}

The function strlen returns the length of the string passed into the constructor. Notice that the

Employee name is now stored in a dynamically allocated character array. It is of "string

length + 1" to allow for the null terminator used with C-style strings, '\0'. The strcpy function

automatically adds the null terminator to the destination string. Also, notice that the

destructor frees the memory used to hold the employee name. This is needed to avoid a

memory leak

Page 113: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

113 [email protected]

Unit 6: Operator overloading and type conversions (10 HOURS) THEORY At the end of the unit the student should be able to: 1. ..define operator overloading 2. ..overload:

- Unary operators - Binary operators - Binary operators using friends

3. ..manipulate strings using operators 4. ..list the rules for overloading operators 5. ..make type conversions

Operator Overloading

Operator overloading completes the data abstraction facilities. "data abstraction" means

programmer-defined types which can be used with the same flexibility as built-in types. The

class concept was the first step toward this capability. Operator overloading completes the

implementation. This facility allows the programmer to define how meaningful standard C++

operators can be used with a class.

6.1 It's All Notation

Really all that's happening is a notational trick. By giving a member or non-member function

a special name, we indicate to the compiler that it should consider it when it runs into the use

of a particular operator involving a class. When the compiler is looking at a+b it's as if it saw

a.operator+(b) or operator+(a,b). +a can be interpreted as a.operator+() or

operator+(a).

A non-member function implementation of a binary operation has the additional flexibility of

being able to apply conversions to the first argument.

References are commonly used as arguments. This is where the reference syntax becomes

valuable since it allows the usual operator notation while providing the efficiency that comes

with passing pointers to classes instead of (possibly constructed) copies. Be careful when

returning references though. Don't use references to local objects which are destroyed when

the function exits.

6.2 General Restrictions

Page 114: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

114 [email protected]

The usual rules of function call overloading apply, plus it must be remembered that the built-

in operators are prospective candidates for resolving any call, and there are the following

general restrictions:

• The standard C++ precedences and associativities determine how any expression will

be parsed and can't be changed.

• No new operators can be invented, e.g. @ can't be overloaded as an operator.

• The operator must be written as unary or binary depending on its use with the built-in

types, e.g. a binary operator can't be overloaded in a unary way for a class if there's no

built-in type for which it's used in a unary manner.

• For non-member functions overloading operators, at least one function argument must

be an instance or a reference to a class. This ensures no C++ code can change the

built-in behavior of operators with built-in types.

• No default values for the operator arguments are allowed.

• There are also operator-specific restrictions, notations and features which are

enumerated below.

The following operators can't be overloaded: `.', `.*', `::', sizeof, () value construction and

the ternary conditional expression operator (`?:').

The following operators must be implemented as member functions:

= -> () []

6.3 Guidelines

The good news is that the programmer has complete control over the return type and

argument types of the function. This flexibility must be used with some sensitivity. For

example, + should be overloaded for a class only when replacing functional notation for an

operation analagous to addition for the class. Unless there is a good reason for doing

otherwise, it should mimic the behavior of the built-in operator as much as possible meaning

(for a function overloading +):

• It shouldn't change the value of either operand, since + doesn't do that when applied to

built-in types.

• It should be commutative.

As another example, it might be a good idea for overloaded = to return a reference to the left

operand.

Each operator has a sort of "culture", a way programmers expect it to behave given their

experience with built-in types. The more a new version of the operator fits in with this

experience, the easier it will be for the programmer to utilize it in an effective and error-free

manner. In addition, the class will be more likely to fit into and work properly in templates

that require the operator.

6.4 Operator-specific restrictions, notations and features

Copy assignment operator

Page 115: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

115 [email protected]

One operator which frequently needs to be explicitly defined for a safe class interface is the

copy assignment operator. This is because, if one is not defined explicitly, the compiler

generates a default version which does a member-wise copy. The copy assignment operator

has a reference or value of the same type as its argument. This "feature" is for backward

compatibility with C.

It can have the same terrible problems in conjunction with dynamically allocated members as

the copy constructor does.

In designing assignment operation, the effects of assigning an object to itself must be taken

into account. This may seem silly at first glance, but it is a very real possibility when

indirection or references are being used.

Other assignment operators

Behavior of overloaded += is independent (and must be defined separately and explicitly to

be used) from the behavior of overloaded + and =. This applies to the rest of the assignment

operators as well. It often makes sense to define binary + using the (usually simpler) +=

operation. += will usually be faster since it doesn't require construction of a temporary to hold

the final result since the final result is stored in an existing variable.

operator++ and operator--

These two unary operators have prefix and postfix versions. The prefix version is

implemented as with the other unary operators. The postfix version must be implemented as

a.operator++(int) or operator++(a, int). The int argument is a dummy which is not

used for anything.

Incidentally, in C++, the assignment operators and prefix ++ and -- result in l-values contrary

to their behavior in C. Again, overloaded versions of these operators should behave as the

built-in types if not overly inconvenient. Here inefficiency can be a big concern as the built-in

behavior for the postfix version of these operators is to return by value a snap shot preserving

the state of the object before it is operated on. For a large object where copy construction is

expensive, this could be prohibitive.

operator() function call

Overloading this enables instances of the class to be treated as if they were function

identifiers. It can be overloaded several times for varying argument lists. Can be very useful.

operator->

Overloaded versions of this operator could well be termed "pass the buck" operators. This is

implemented as a unary member function and allows -> to be applied to an instance of a

class, whereas the built-in version always requires a pointer to a class or struct.

A name of a data or function member must appear on the right side of the operator. If the

operator returns a pointer to an object, that data or function access must make sense for the

object. If the operator returns a reference or instance of a class, that class must in turn have

Page 116: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

116 [email protected]

the -> operator overloaded. Thus, one usage of this operator could potentially result in many

functions being called if the buck is passed extensively, though in practice it is usually just

one layer deep.

This is useful for smart pointers. A program can defer construction of an object or loading of

data until access makes it necessary.

new and delete

The sort of overloading which can be done here is restricted to determining where run-time

memory is obtained when an object is created via these operators. Typically they are used to

optimize heap memory allocation for a class. For example, if a Tree class created many

instances of a Node class, it may be more economical to allocate them in batches, or to check

a list of "used" nodes before trying to allocate a new one.

The format of the delete member function is

void operator delete(void *, std::size_t)

The second argument may be omitted.

The format of the new member function is

void *operator new(std::size_t)

Additional arguments of arbitrary type may be added after the initial std::size_t type. If

these arguments appear, they are supplied after the new invocation in function call format, i.e.

new(...args...) MyClass. It always returns a void * type. Even so, the expression where

it is applied has the type of a pointer to the type which is being allocated as is the case with

the built-in operator.

Conversion functions

casts (and conversions in general via assignment, C-style cast, C++ style cast) can be

"overloaded" as well, but it is conceptually distinct since the return type is fixed (can't be

programmer-defined as in general case) and they can only be defined as member functions,

not friends. It looks similar though. An int conversion function is defined as the member

function operator int(). It has no return value and no arguments. If a conversion function

is to be written for a complex type, a typedef must be used so it can be manipulated as a

single word.

The array of needed implementations of an operator can be reduced by defining conversions

for the classes involved. Conversions to a class are defined implicitly with single-argument

constructors. Conversions from the class are defined using conversion functions and exist by

virtue of polymorphism.

Page 117: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

117 [email protected]

Unit 7: Inheritance: Extending class (25 HOURS) THEORY At the end of the unit the student should be able to: 1. ..define derived classes 2. ..describe single inheritance 3. ..make a private member inheritable 4. ..describe multilevel inheritance 5. ..describe multiple inheritance 6. ..describe hierarchical inheritance 7. ..describe hybrid inheritance 8. ..describe virtual base classes 9. ..describe abstract classes 10. ..use constructors in derived classes 11. ..use member classes: Nesting of classes

Inheritance

Inheritance is the concept to inherit the properties of one class to another class. This has also

known as class structure again. For example, classes A contains two-member function ads

and subtracts and class b contain two another functions multiply and divide. We want to use

all these function with one object then we need to use inheritance where class B inherits all

the property of class, which is public, but class B cannot use the private properties of class A.

There are following types of inheritance:

Inheritance can be classified to 5 types.

1. Single Inheritance 2. Hierarchical Inheritance 3. Multi Level Inheritance 4. Hybrid Inheritance 5. Multiple Inheritance

1. Single Inheritance

when a single derived class is created from a single base class then the inheritance is called as single inheritance. When class a gas inherited in class has

Page 118: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

118 [email protected]

known as base class and B class is know as derived class. Here only two classes have linked

to each other.

2. Hierarchical Inheritance

When more than one derived class are created from a single base class, then that inheritance is called as hierarchical inheritance.

3. Multi Level Inheritance

In this type of inheritance, there are number of level and it has used in that cases where we

want to use all properties in number of levels according to the requirement. For example,

class A inherited in class b and class b has inherited in class c for class b so on. Where class

A is base class c. In another way we can say b is derived class a base class for c and a indirect

base class for c is indirect base class for c and c indirect derived class for class A.

Page 119: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

119 [email protected]

When a derived class is created from another derived class, then that inheritance is called as multi level inheritance.

4. Hybrid Inheritance

Any combination of single, hierarchical and multi level inheritances is

called as hybrid inheritance.

Page 120: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

120 [email protected]

5. Multiple Inheritance In this type of inheritance, number of classes has inherited in a single class. Where two or

more classes are, know as base class and one is derive class.

when a derived class is created from more than one base class then that inheritance is called as multiple inheritance. But multiple inheritance is

not supported by .net using classes and can be done using interfaces.

Handling the complexity that causes due to multiple inheritance is very complex. Hence it was not supported in dotnet with class and it can be

done with interfaces. Inheritance, Samples of using inheritance

Page 121: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

121 [email protected]

Inheritance is the property by which one object can inherit the properties of the other object.

A general class can be inherited by the other classes. A class that is inherited is called a base

class. A class which is inheriting another class is called a derived class. When a class inherits

another class, members of the base class become the members of the derived class. The

general form of inheritance is:-

class derived_name : access_specifier base_name

{

};

The derived_name is the name of the derived class. The base_name is the name of the base

class. The access_specifier can be private, public or protected. If the access_specifier is

public then all public members of the base class become public members of the derived class

and protected members of the base class become the protected members of the derived class.

If the access_specifier is private then all public and protected members of the base class will

become private members of the derived class. If the access_specifier is protected then the

public and protected members of the base class become the protected members of the derived

class. Whether access_specifier is public, private or protected, private members of the base

class will not be accessed by the members of the derived class.

The access_specifier protected provides more flexibility in terms of inheritance. The private

members of the base class cannot be accessed by the members of the derived class. The

protected members of the base class remain private to their class but can be accessed and

inherited by the derived class. The protected members of the base class will remain private to

the other elements of the program.

A derived class can inherit one or more base classes. A constructor of the base is executed

first and then the constructor of derived class is executed. A destructor of derived class is

called before the destructor of base class. The arguments to the base class constructor can be

passed as follows:-

derived_constructor (argument list): base1 (arg_list)

base2(arg_list1)

baseN(arg_list)

The derived_constructor is the name of the derived class. The argument list is list of the data

members of the derived class. The base1 is name of the base class. The arg_list is the list of

the members of the base class. Here is a program which illustrates the features of inheritance.

#include<iostream>

using namespace std;

class shape

{

private :

double length;

Page 122: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

122 [email protected]

protected:

double breadth;

public :

double len()

{

return(length);

}

shape(double length1,double breadth1)

{

length=length1;

breadth=breadth1;

}

//shape() { }

};

class shape1

{

public:

double height;

shape1(double height1)

{

height=height1;

}

//shape1() { }

};

class cuboid : public shape, private shape1

{

public:

cuboid(double length1,double breadth1,double

height1):shape(length1,breadth1),shape1(height1)

{

cout << " A constructor is called " << endl;

}

double volume()

{

return(height*breadth*len());

}

double bre()

{

return(breadth);

}

double ht()

{

Page 123: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

123 [email protected]

return(height);

}

};

int main()

{

cuboid c1(2.4,3.5,6.7);

cout << "The length of the cuboid is : " << c1.len() << endl;

cout << "The breadth of the cuboid is : " << c1.bre() << endl;

cout << "The height of the cuboid is : " << c1.ht() << endl;

cout << "The volume of the cuboid is : " << c1.volume() << endl;

return(0);

}

The result of the program is:-

The program has two base classes shape and shape1 and one derived class called cuboid

which inherits shape as public and shape1 as private. The public and protected members of

shape become pubic and protected members of derived class cuboid. The private members of

shape remain private to the class shape. The members of shape1 class become the private

members of the derived class cuboid.

The statement

class cuboid : public shape, private shape1

states that class cuboid inherits class shape as public and class shape1 as private. The

statement

cuboid(double length1,double breadth1,double

height1):shape(length1,breadth1),shape1(height1)

{

cout << " A constructor is called " << endl;

}

declares the constructor of the class cuboid. When constructor of class cuboid is called first

constructor of shape is executed and then constructor of shape1 is executed and after that the

constructor of cuboid is executed. The statements

double volume()

{

return(height*breadth*len());

Page 124: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

124 [email protected]

}

calculate the volume of the cuboid. The class cuboid cannot access the private data member

length of the shape class. It access the length by calling the function len() which returns the

private data member length. The data member breadth becomes the protected member of the

class cuboid. The height which is public member of shape1 class becomes the private

member of the class cuboid as it inherits the shape 1 class as private. The statements

double bre()

{

return(breadth);

}

returns the breadth of the cuboid as data member breadth cannot be accessed outside the class

as it is protected member of cuboid. The statement

double ht()

{

return(height);

}

returns the height of the cuboid as data member height cannot be accessed outside the class as

height is the private data member of the class cuboid. The statement

cuboid c1(2.4,3.5,6.7);

creates an object c1 of type cuboid. The constructor is called to initialize the values of the

cuboid. The constructor of shape is executed and then constructor of shape1 is executed and

then finally constructor of cuboid is executed. The statement

cout << "The length of the cuboid is : " << c1.len() << endl;

displays the length of the cuboid as c1.len() calls the len() function of class shape which is

also the public member function of cuboid. The statement

cout << "The breadth of the cuboid is : " << c1.bre() << endl;

displays the breadth of the cuboid. As the data member breadth cannot be accessed directly as

it is protected member of the class cuboid so the function bre() returns the breadth of the

cuboid. The statement

cout << "The height of the cuboid is : " << c1.ht() << endl;

displays the height of the cuboid. The data member height cannot be accessed directly as it is

private member of class cuboid so it is accessed through the function ht() which returns

height.

Page 125: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

125 [email protected]

Unit 8: Pointers, virtual functions and polymorphism (25 HOURS)

THEORY At the end of the unit the student should be able to: 1. ..employ pointers to objects 2. ..employ the “this” pointer 3. ..employ pointers to derived classes 4. ..describe virtual functions 5. ..describe pure virtual functions

Polymorphism and Virtual functions

Polymorphism is defined as one interface to control access to a general class of actions. There

are two types of polymorphism one is compile time polymorphism and the other is run time

polymorphism. Compile time polymorphism is functions and operators overloading. Runtime

time polymorphism is done using inheritance and virtual functions.

Function Overloading

Polymorphism means that functions assume different forms at different times. In case of

compile time it is called function overloading. For example, a program can consist of two

functions where one can perform integer addition and other can perform addition of floating

point numbers but the name of the functions can be same such as add. The function add() is

said to be overloaded. Two or more functions can have same name but their parameter list

should be different either in terms of parameters or their data types. The functions which

differ only in their return types cannot be overloaded. The compiler will select the right

function depending on the type of parameters passed. In cases of classes constructors could

be overloaded as there can be both initialized and unintialized objects. Here is a program

which illustrates the working of compile time function overloading and constructor

overloading.

#include<iostream>

using namespace std;

class employee

{

public:

int week;

int year;

double calculate(double salary)

Page 126: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

126 [email protected]

{

return(salary*week);

}

int calculate(int salary)

{

return(salary*week*year);

}

employee(int week1)

{

week=week1;

}

employee(int week1,int year1)

{

week=week1;

year=year1;

}

};

int main()

{

int sal;

double sal2;

employee emp1(10);

employee emp2(10,3);

cout << "Enter the no years for first employee" << endl;

cin >> emp1.year;

cout << endl << "Enter the salary per week for first employee" << endl;

cin >> sal;

cout << "The total salary of first employee is : " << emp1.calculate(sal) << endl;

cout << endl << "Enter the salary per week for second employee is : " << endl;

cin >> sal2;

cout << "The total salary of second employee is for one year: " <<

emp2.calculate(sal2) << endl;

return(0);

}

The result of the program is:-

In the program function calculate() and constructor of class employee are overloaded. The

function calculate() is declared two times but with different parameter type and same with

Page 127: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

127 [email protected]

constructor employee which is also declared two times but with different parameter types.

The following statements

double calculate(double salary)

{

return(salary*week);

}

int calculate(int salary)

{

return(salary*week*year);

}

declare functions with same name calculate but one has parameter type integer and other has

parameter type double. The function calculate() is overloaded. The statements

employee(int week1)

{

week=week1;

}

employee(int week1,int year1)

{

week=week1;

year=year1;

}

declare two constructors of class employee where one constructor’s parameter list is different

from other constructor’s parameter list. The constructor is overloaded. The statement

employee emp1(10);

declares an object emp1 of type employee. When object is created first constructor is called

since the argument list matches with parameter list of the constructor. The constructor

initializes the data member week of the object emp1. The statement

employee emp2(10,3);

declares an object emp2 of type employee. The second constructor is called since the

argument list matches with the parameter list of the constructor. The constructor initializes

the data members week and year of the object emp2. In the statement

cout << "The total salary of first employee is : " << emp1.calculate(sal) << endl;

emp1.calculate(sal) calls the first function calculate as the data type of sal matches with the

parameter of the function calculate. It displays the total salary which is salary*week*year. In

the following statement

cout << "The total salary of second employee is for one year: " <<

emp2.calculate(sal2) << endl;

Page 128: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

128 [email protected]

emp2.calculate(sal2) calls the second function calculate as the data type of sal2 which is

double matches with the data type of parameter of function calculate and hence second

function is called. It displays the total salary which is salary*week.

Operator Overloading

In polymorphism operators can also be overloaded. Operators can be overloaded in order to

perform special functions with respect to the class. With the help of operator overloading

standard operations such as + , - , * , etc can be applied on the objects of the class. Operators

are overloaded by creating operator functions. The keyword operator is used to define

operator function. Operator overloading doesn’t allow creating new operators. The general

form of operator function is:-

return_type operator #(arg_list)

{

}

return_type is the data type of the value returned from the function. The arg_list is the list of

the arguments to the function. The operator comes after the keyword operator. Instead of #

there will be an operator. Here is a program to show operator overloading.

#include<iostream>

using namespace std;

class rectangle

{

public:

int length;

int breadth;

rectangle(int length1,int breadth1)

{

length=length1;

breadth=breadth1;

}

int operator+(rectangle r1)

{

return(r1.length+length);

}

};

int main ()

{

rectangle r1(10,20);

rectangle r2(40,60);

int len;

len=r1+r2;

cout << "The total length of the two rectangles is : " << len << endl;

Page 129: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

129 [email protected]

return(0);

}

The result of the program is:-

The program consists of operator + function which is overloaded. The + operator is used to

perform addition of the length of the objects. The statements

int operator+(rectangle r1)

{

return(r1.length+length);

}

define the operator function whose return type is integer. The operator + is overloaded. The

function is used to add the lengths of the two objects. The parameter list consists of one

object of type rectangle. The operator()+ takes only one parameter as the operand on the left

side of the operator + is passed implicitly to the function through the this operator. The

statement

len=r1+r2;

calls the operator()+ function to calculate the length of the two objects. The return type is of

integer. The variable len will contain the total of length of the objects.

Virtual Functions

A virtual function is a member function of the base class and which is redefined by the

derived class. When a derived class inherits the class containing the virtual function, it has

ability to redefine the virtual functions. A virtual function has a different functionality in the

derived class. The virtual function within the base class provides the form of the interface to

the function. Virtual function implements the philosophy of one interface and multiple

methods. The virtual functions are resolved at the run time. This is called dynamic binding.

The functions which are not virtual are resolved at compile time which is called static

binding. A virtual function is created using the keyword virtual which precedes the name of

the function.

Virtual functions are accessed using a base class pointer. A pointer to the base class can be

created. A base class pointer can contain the address of the derived object as the derived

object contains the subset of base class object. Every derived class is also a base class. When

a base class pointer contains the address of the derived class object, at runtime it is decided

which version of virtual function is called depending on the type of object contained by the

pointer. Here is a program which illustrates the working of virtual functions.

include<iostream>

using namespace std;

Page 130: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

130 [email protected]

class shape

{

public:

int side;

virtual int volume()

{

cout << endl <<"Virtual function of base class " << endl;

return(0);

}

};

class cube: public shape

{

public:

int volume()

{

cout << endl << "Volume function of cube " << endl;

return(side*side*side);

}

};

class cuboid:public shape

{

public:

int breadth;

int height;

int volume()

{

cout << endl << "Volume function of cuboid " << endl;

return(side*breadth*height);

}

};

int main()

{

shape *s,s1;

cube c1;

cuboid c2;

cout << "Enter the side of the cube" << endl;

cin >> c1.side;

cout << endl << "Enter the side of the cuboid " << endl;

cin >> c2.side;

cout << endl << "Enter the breadth of the cuboid" << endl;

cin >> c2.breadth;

cout << endl << "Enter the height of the cuboid" << endl;

cin >> c2.height;

Page 131: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

131 [email protected]

s=&s1;

s->volume();

s=&c1;

cout << endl << "The volume of the cube " << s->volume() << endl;

s=&c2;

cout << endl << "The volume of the cuboid " << s->volume() << endl;

return(0);

}

The result of the program is:-

The program has base class shape and class cube and cuboid which inherits base class. The

base class has virtual function volume. The statements

virtual int volume()

{

cout << endl <<"Virtual function of base class " << endl;

return(0);

}

define the member function volume() of base class. The function is virtual. The keyword

virtual precedes the function return type. In the following statements

int volume()

{

cout << endl << "Volume function of cube " << endl;

return(side*side*side);

}

the derived class cube which inherits base class shape, redefines the function volume() which

is virtual. In the following statements

Page 132: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

132 [email protected]

int volume()

{

cout << endl << "Volume function of cuboid " << endl;

return(side*breadth*height);

}

the derived class cuboid which inherits the base class shape, redefines the function volume().

The statement

shape *s,s1;

declares a pointer to the base class shape. The statement

s=&s1;

pointer s contains the address of the base class object s1. The statement

s->volume();

calls the function volume of the base class shape as the pointer contains the address of the

base class object. The statement

s=&c1;

pointer s now contains the address of the derived class object c1. The statement

cout << endl << "The volume of the cube " << s->volume() << endl;

displays the volume of the cube as s->volume() calls the function volume of the derived class

cube. The pointer s contains the address of the object of derived class cube. In the statement

s=&c2;

pointer s now contains the address of the derived class object c2. The statement

cout << endl << "The volume of the cuboid " << s->volume() << endl;

displays the volume of the cuboid as s->volume() calls the function volume of the derived

class cuboid. The pointer s now contains the address of the object of derived class cuboid.

When a virtual function is not defined by the derived class, the version of the virtual function

defined by the base class is called. When a derived class which contains the virtual function

is inherited by another class, virtual function can be overloaded for the new derived class.

This means that virtual function can be inherited.

A pure virtual function is a function which contains no definition in the base class. The

general form of virtual function is:-

Page 133: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

133 [email protected]

virtual return_type function_name(para_list)=0;

The return_type is the type of the value returned. The function_name is the name of the

function and para_list is the parameter list.

Each derived class should contain the definition of virtual functions. If the derived class does

not define virtual function then compiler will generate an error. A class which contains one or

more pure virtual function is called abstract class. Objects of abstract class cannot be created

as it does not contain definition of one or more functions. The pointers of abstract class can

be created and the references to the abstract class can be made. Here is a same program which

shows how pure virtual function is defined.

#include<iostream>

using namespace std;

class shape

{

public:

int side;

virtual int volume()=0;

};

class cube: public shape

{

public:

int volume()

{

cout << endl << "Volume function of cube " << endl;

return(side*side*side);

}

};

class cuboid:public shape

{

public:

int breadth;

int height;

int volume()

{

cout << endl << "Volume function of cuboid " << endl;

return(side*breadth*height);

}

};

int main()

{

shape *s;

Page 134: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

134 [email protected]

cube c1;

cuboid c2;

cout << "Enter the side of the cube" << endl;

cin >> c1.side;

cout << endl << "Enter the side of the cuboid " << endl;

cin >> c2.side;

cout << endl << "Enter the breadth of the cuboid" << endl;

cin >> c2.breadth;

cout << endl << "Enter the height of the cuboid" << endl;

cin >> c2.height;

s=&c1;

cout << endl << "The volume of the cube " << s->volume() << endl;

s=&c2;

cout << endl << "The volume of the cuboid " << s->volume() << endl;

return(0);

}

The result of the program is:-

The statement

virtual int volume()=0;

declares pure virtual function volume() which has no definition. The class shape is now

abstract class and objects of type shape cannot be created.

Page 135: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

135 [email protected]

Unit 9: Working with files (25 HOURS) THEORY At the end of the unit the student should be able to: 1. ..employ classes for file stream operators 2. ..open and close a file 3. ..detect an end-of-line 4. ..distinguish between file modes 5. ..know about file pointers and their manipulators 6. ..employ sequential input and output operations 7. ..to update a file: random access 8. ..take care of error handling during file operations 9. ..use command-line arguments

Input/Output with files C++ provides the following classes to perform output and input of characters to/from files:

• ofstream: Stream class to write on files • ifstream: Stream class to read from files • fstream: Stream class to both read and write from/to files.

These classes are derived directly or indirectly from the classes istream, and ostream. We have already used objects whose types were these classes: cin is an object of class istream and cout is an object of class ostream. Therfore, we have already been using classes that are related to our file streams. And in fact, we can use our file streams the same way we are already used to use cin and cout, with the only difference that we have to associate these streams with physical files.

Let's see an example:

// basic file operations #include <iostream> #include <fstream> using namespace std; int main () { ofstream myfile; myfile.open ("example.txt"); myfile << "Writing this to a file.\n"; myfile.close(); return 0; } [file example.txt]

Page 136: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

136 [email protected]

Writing this to a file

This code creates a file called example.txt and inserts a sentence into it in the same way we are used to do with cout, but using the file stream myfile instead.

But let's go step by step:

Open a file

The first operation generally performed on an object of one of these classes is to associate it to a real file. This procedure is known as to open a file. An open file is represented within a program by a stream object (an instantiation of one of these classes, in the previous example this was myfile) and any input or output operation performed on this stream object will be applied to the physical file associated to it.

In order to open a file with a stream object we use its member function open():

open (filename, mode);

Where filename is a null-terminated character sequence of type const char * (the same type that string literals have) representing the name of the file to be opened, and mode is an optional parameter with a combination of the following flags:

ios::in Open for input operations. ios::out Open for output operations. ios::binary Open in binary mode.

ios::ate Set the initial position at the end of the file. If this flag is not set to any value, the initial position is the beginning of the file.

ios::app All output operations are performed at the end of the file, appending the content to the current content of the file. This flag can only be used in streams open for output-only operations.

ios::trunc If the file opened for output operations already existed before, its previous content is deleted and replaced by the new one.

All these flags can be combined using the bitwise operator OR (|). For example, if we want to open the file example.bin in binary mode to add data we could do it by the following call to member function open():

ofstream myfile;

myfile.open ("example.bin", ios::out | ios::app | ios::binary);

Each one of the open() member functions of the classes ofstream, ifstream and fstream has a default mode that is used if the file is opened without a second argument:

class default mode parameter

ofstream ios::out

Page 137: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

137 [email protected]

ifstream ios::in fstream ios::in | ios::out

For ifstream and ofstream classes, ios::in and ios::out are automatically and respectivelly assumed, even if a mode that does not include them is passed as second argument to the open() member function.

The default value is only applied if the function is called without specifying any value for the mode parameter. If the function is called with any value in that parameter the default mode is overridden, not combined.

File streams opened in binary mode perform input and output operations independently of any format considerations. Non-binary files are known as text files, and some translations may occur due to formatting of some special characters (like newline and carriage return characters).

Since the first task that is performed on a file stream object is generally to open a file, these three classes include a constructor that automatically calls the open() member function and has the exact same parameters as this member. Therefor, we could also have declared the previous myfile object and conducted the same opening operation in our previous example by writing:

ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);

Combining object construction and stream opening in a single statement. Both forms to open a file are valid and equivalent.

To check if a file stream was successful opening a file, you can do it by calling to member is_open() with no arguments. This member function returns a bool value of true in the case that indeed the stream object is associated with an open file, or false otherwise:

if (myfile.is_open()) { /* ok, proceed with output */ }

Closing a file

When we are finished with our input and output operations on a file we shall close it so that its resources become available again. In order to do that we have to call the stream's member function close(). This member function takes no parameters, and what it does is to flush the associated buffers and close the file:

Page 138: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

138 [email protected]

myfile.close();

Once this member function is called, the stream object can be used to open another file, and the file is available again to be opened by other processes.

In case that an object is destructed while still associated with an open file, the destructor automatically calls the member function close().

Text file streams are those where we do not include the ios::binary flag in their opening mode. These files are designed to store text and thus all values that we input or output from/to them can suffer some formatting transformations, which do not necessarily correspond to their literal binary value.

Data output operations on text files are performed in the same way we operated with cout:

// writing on a text file #include <iostream> #include <fstream> using namespace std; int main () { ofstream myfile ("example.txt"); if (myfile.is_open()) { myfile << "This is a line.\n"; myfile << "This is another line.\n"; myfile.close(); } else cout << "Unable to open file"; return 0; } [file example.txt] This is a line. This is another line.

Data input from a file can also be performed in the same way that we did with cin:

// reading a text file #include <iostream> #include <fstream> #include <string> using namespace std; int main () { string line;

Page 139: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

139 [email protected]

ifstream myfile ("example.txt"); if (myfile.is_open()) { while (! myfile.eof() ) { getline (myfile,line); cout << line << endl; } myfile.close(); } else cout << "Unable to open file"; return 0; } This is a line. This is another line.

This last example reads a text file and prints out its content on the screen. Notice how we have used a new member function, called eof() that returns true in the case that the end of the file has been reached. We have created a while loop that finishes when indeed myfile.eof() becomes true (i.e., the end of the file has been reached).

Checking state flags

In addition to eof(), which checks if the end of file has been reached, other member functions exist to check the state of a stream (all of them return a bool value): bad()

Returns true if a reading or writing operation fails. For example in the case that we try to write to a file that is not open for writing or if the device where we try to write has no space left.

fail() Returns true in the same cases as bad(), but also in the case that a format error happens, like when an alphabetical character is extracted when we are trying to read an integer number.

eof() Returns true if a file open for reading has reached the end.

good() It is the most generic state flag: it returns false in the same cases in which calling any of the previous functions would return true.

In order to reset the state flags checked by any of these member functions we have just seen we can use the member function clear(), which takes no parameters.

get and put stream pointers

Page 140: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

140 [email protected]

All i/o streams objects have, at least, one internal stream pointer:

ifstream, like istream, has a pointer known as the get pointer that points to the element to be read in the next input operation.

ofstream, like ostream, has a pointer known as the put pointer that points to the location where the next element has to be written.

Finally, fstream, inherits both, the get and the put pointers, from iostream (which is itself derived from both istream and ostream).

These internal stream pointers that point to the reading or writing locations within a stream can be manipulated using the following member functions:

tellg() and tellp() These two member functions have no parameters and return a value of the member type pos_type, which is an integer data type representing the current position of the get stream pointer (in the case of tellg) or the put stream pointer (in the case of tellp). seekg() and seekp() These functions allow us to change the position of the get and put stream pointers. Both functions are overloaded with two different prototypes. The first prototype is:

seekg ( position ); seekp ( position );

Using this prototype the stream pointer is changed to the absolute position position (counting from the beginning of the file). The type for this parameter is the same as the one returned by functions tellg and tellp: the member type pos_type, which is an integer value.

The other prototype for these functions is:

seekg ( offset, direction ); seekp ( offset, direction );

Using this prototype, the position of the get or put pointer is set to an offset value relative to some specific point determined by the parameter direction. offset is of the member type off_type, which is also an integer type. And direction is of type seekdir, which is an enumerated type (enum) that determines the point from where offset is counted from, and that can take any of the following values:

ios::beg offset counted from the beginning of the stream

ios::cur offset counted from the current position of the stream pointer

Page 141: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

141 [email protected]

ios::end offset counted from the end of the stream

The following example uses the member functions we have just seen to obtain the size of a file:

// obtaining file size #include <iostream> #include <fstream> using namespace std; int main () { long begin,end; ifstream myfile ("example.txt"); begin = myfile.tellg(); myfile.seekg (0, ios::end); end = myfile.tellg(); myfile.close(); cout << "size is: " << (end-begin) << " bytes.\n"; return 0; } size is: 40 bytes.

Random access files

We use two new functions which are write(), a member of ofstream and read(), a member of the ifstream. The pararmeters of read() and write() are the data or variable and its length.

Their prototypes are:

write ( memory_block, size ); read ( memory_block, size );

// Files.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include "fstream.h"

#include "iostream.h"

ofstream dout;

Page 142: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

142 [email protected]

int main()

{

dout.open("stud.txt", ios::out);

char text[5];

cout<<"Enter text"<<endl;

cin>>text;

dout.write(text,sizeof(text));

dout.close();

return 0;

}

Binary files

In binary files, to input and output data with the extraction and insertion operators (<< and >>) and functions like getline is not efficient, since we do not need to format any data, and data may not use the separation codes used by text files to separate elements (like space, newline, etc...).

File streams include two member functions specifically designed to input and output binary data sequentially: write and read. The first one (write) is a member function of ostream inherited by ofstream. And read is a member function of istream that is inherited by ifstream. Objects of class fstream have both members.;

Where memory_block is of type "pointer to char" (char*), and represents the address of an array of bytes where the read data elements are stored or from where the data elements to be written are taken. The size parameter is an integer value that specifies the number of characters to be read or written from/to the memory block.

// reading a complete binary file #include <iostream> #include <fstream> using namespace std; ifstream::pos_type size; char * memblock;

Page 143: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

143 [email protected]

int main () { ifstream file ("example.txt", ios::in|ios::binary|ios::ate); if (file.is_open()) { size = file.tellg(); memblock = new char [size]; file.seekg (0, ios::beg); file.read (memblock, size); file.close(); cout << "the complete file content is in memory"; delete[] memblock; } else cout << "Unable to open file"; return 0; } the complete file content is in memory

In this example the entire file is read and stored in a memory block. Let's examine how this is done:

First, the file is open with the ios::ate flag, which means that the get pointer will be positioned at the end of the file. This way, when we call to member tellg(), we will directly obtain the size of the file. Notice the type we have used to declare variable size:

ifstream::pos_type size;

ifstream::pos_type is a specific type used for buffer and file positioning and is the type returned by file.tellg(). This type is defined as an integer type, therefore we can conduct on it the same operations we conduct on any other integer value, and can safely be converted to another integer type large enough to contain the size of the file. For a file with a size under 2GB we could use int:

int size;

size = (int) file.tellg();

Once we have obtained the size of the file, we request the allocation of a memory block large enough to hold the entire file:

memblock = new char[size];

Right after that, we proceed to set the get pointer at the beginning of the file (remember that we opened the file with this pointer at the end), then read the entire file, and finally close it:

file.seekg (0, ios::beg);

Page 144: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

144 [email protected]

file.read (memblock, size); file.close();

At this point we could operate with the data obtained from the file. Our program simply announces that the content of the file is in memory and then terminates.

Buffers and Synchronization

When we operate with file streams, these are associated to an internal buffer of type streambuf. This buffer is a memory block that acts as an intermediary between the stream and the physical file. For example, with an ofstream, each time the member function put (which writes a single character) is called, the character is not written directly to the physical file with which the stream is associated. Instead of that, the character is inserted in that stream's intermediate buffer.

When the buffer is flushed, all the data contained in it is written to the physical medium (if it is an output stream) or simply freed (if it is an input stream). This process is called synchronization and takes place under any of the following circumstances:

• When the file is closed: before closing a file all buffers that have not yet been flushed are synchronized and all pending data is written or read to the physical medium.

• When the buffer is full: Buffers have a certain size. When the buffer is full it is automatically synchronized.

• Explicitly, with manipulators: When certain manipulators are used on streams, an explicit synchronization takes place. These manipulators are: flush and endl.

• Explicitly, with member function sync(): Calling stream's member function sync(), which takes no parameters, causes an immediate synchronization. This function returns an int value equal to -1 if the stream has no associated buffer or in case of failure. Otherwise (if the stream buffer was successfully synchronized) it returns 0.

Details of file I/O seem to be buried at the back, missing, or overly complicated in most C++ manuals. This page provides a quick reference for the most frequently used methods.

This page only discusses basic options that seem to be common to all my C++ references. Apparently there is a lot of variation from one manual to another, and from one implementation to another. I believe the methods below to be safe and portable, at least for ASCII (human-readable text) files.

Header files

Page 145: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

145 [email protected]

To do input and output, you will need to load the iostream header file. You may also need to load the fstream (file I/O) and/or iomanip (format manipulation) header files. Put some/all of the following lines at the top of your code file (or in the header file for your program, if you are using one).

#include <iostream.h> // I/O #include <fstream.h> // file I/O #include <iomanip.h> // format manipulation

Getting a stream

Three streams just exist: cout (terminal output), cin (terminal input), and cerr (error output, which also goes to the terminal).

When writing error messages, use cerr rather than cout. In simple examples, the two appear to be the same. However, they behave differently when you use Unix redirection operators when you run your program. In particular, if you redirect output to a file, error messages printed to cerr will still appear on the user's terminal whereas error messages printed to cout will be mixed into the output file.

File streams are of type ifstream (input) or ofstream (output).

ifstream fp_in; // declarations of streams fp_in and fp_out ofstream fp_out; fp_in.open("myfile.txt", ios::in); // open the streams fp_out.open("myfile.txt", ios::out); fp_in.close(); // close the streams fp_out.close();

A file should be closed if you are done with it, but the program will continue running for a while longer. This is particularly important when you intend to open a lot of files, as there may be a limit on how many you can have open at once. It is also a good idea if you intend to open a file for input, and then re-open the file for output.

Declaring the pointer and opening the file can be combined:

ifstream fp_in("myfile.txt", ios::in); // declare and open

The parameters ios::in and ios::out specify the mode in which the file is to be opened.

Page 146: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

146 [email protected]

Depending on the implementation of C++, it may be possible to specify a variety of other mode options, such as appending to the end of an existing file, triggering an error rather than overwriting an existing file, or specifying that a file is binary for operating systems (e.g. MS-DOS) which distinguish binary and ASCII files.

Passing streams to functions

File streams must be passed to functions by reference, not by value.

void myfunction(ifstream &fp, ...) // use this void myfunction(ifstream fp, ...) // not this

If you pass streams by value, the C++ compiler will not complain. However, mysterious bad things will start happening, often in parts of the code which don't appear to be related to the offending function.

Item by item input and output

If each input item is surrounded by whitespace (blanks, tabs, newlines), the items can be read easily using the extraction operator >>.

int myinteger; // declarations float myfloat; char mychar; char *mystring; // two ways to declare a string char mystring[64]; fp_in >> myinteger; // input from file pointer or standard input cin >> myfloat; fp_in >> mychar; cin >> mystring;

The extraction operator works for numbers (ints, floats), characters (char), and strings (declared as arrays of type char or pointers to type char).

The extraction operator returns a zero value if it encounters a problem (typically, the end of the file). Therefore, it can be used as the test in an if statement or a while loop.

WARNING: when reading data into a character string, bad things will happen if the input word is longer than your string. To avoid problems, use the operator setw to force excessively long input to be broken up. (You must include the iomanip header file.) The input to setw should be the length of your string (including the null character '\0' at the end of the string).

Page 147: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

147 [email protected]

cin >> setw(length) >> mystring;

Numbers, characters, and strings can be written to a file, standard output, or the standard error using the insertion operator <<.

cout << "Value of myinteger " << myinteger << endl; cout << "My string is " << mystring << " plus a null character\n" << flush;

To insert a line break, either insert the magic variable endl or write the end-of-line character ('\n') to the output.

To make a pointer print out as a pointer, not as whatever type of data it points to, cast it to the type (void *). To make a character print as a number, cast it to type int. Similarly, you can use a cast to convince C++ to print an integer as the corresponding character.

cout << (void *)ptr; cout << (int)ch; cout << (char)ival;

Buffering and flush

When you send output to a stream, it does not necessarily get printed immediately. Rather, it may wait in a buffer until some unspecified event, e.g. buffer full enough, reading from input, or exit from program. The details may vary.

Buffering makes it faster to print a large amount of output, particularly if you are producing the output bit-by-bit (e.g. one character at a time). However, it is a nuisance for output used in debugging (e.g. a statement that informs you that step 3 of your algorithm has been finished).

Forcing all buffered output to actually be printed is known as "flushing" the stream. A flush can be forced by calling the flush function associated with each output stream, inserting the magic variable flush into the stream, or inserting endl.

cout << flush; cout.flush(); cout << endl;

Other input operations

Page 148: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

148 [email protected]

All of the following are illustrated using the standard input, but they work just the same on file streams.

cin.get(char &ch) Puts the next input character in the variable ch. Returns an integer value, which is zero if it encountered a problem (e.g. end of file).

cin.getline(char *buffer, int length) Reads characters into the string buffer, stopping when (a) it has read length-1 characters or (b) when it finds an end-of-line character ('\n') or the end of the file. Stores a null character ('\0') after the last character read.

cin.read(char *buffer, int n) Reads n bytes (or until the end of the file) from the stream into the buffer.

cin.gcount() Returns the number of characters read by a preceding get, getline, or read command.

cin.ignore(int n) Remove the next n characters (or until end of file) from the input stream, throwing them away into the Great Bit Bucket.

cin.putback(char ch) Puts character ch back onto the stream. Bad things will happen if this character is not the one most recently extracted from the stream.

These operations all return zero if something goes wrong, e.g. they hit the end of the file. Therefore, they can be used as the condition in an if statement or while loop.

In addition, there are two more input operations, get and peek. These functions return EOF (which is secretly -1) if they encounter the end of the file. The output of these functions should be put into an integer (not a char) variable.

cin.get()

Returns the next character in the stream. cin.peek()

Returns the next character in the stream but does not remove it from the stream.

The following functions can be used to test the status of a stream. They return an integer, which is either zero or non-zero.

cin.good()

Returns 0 if the stream has encountered problems such as reading the end of file, non-existent file.

cin.bad()

Returns non-zero value if the stream is totally unusable, e.g. the file cannot be opened (but not if the stream has merely hit the end of the file).

cin.eof()

Page 149: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

149 [email protected]

Returns a non-zero value if the stream has hit the end of the file.

Notice that the stream's status will change to bad (not good, eof, etc) after the first read request which encounters a problem. So, to use one of these functions, you attempt to do what you wanted to do (e.g. open the file, read the next number from the file, ...). If the action can't succeed, the program won't crash, though some of your variables might not contain the values you intended. Next, use the status function to check whether the action succeeded.

Other output operations

Other options for writing data to an output stream are:

cout.put(char ch) Puts ch onto the stream.

cout.write(char *str, int n) Puts n characters onto the stream, reading them from the string str.

The function setf can be used to change formatting parameters for an output stream. For example, the following causes numbers to be left justified.

cout.setf(ios::left); \\ set option cout.unsetf(ios::left); \\ unset option

The most obviously useful parameters are:

ios::left

Left justify output. ios::right

Right justify output. ios::scientific

Print floating point numbers using scientific notation. ios::fixed

Print floating point numbers using fixed point notation. ios::showpoint

Print a decimal point for all floating point numbers, even when it's not needed (e.g. the number is exactly an integer).

The precision of numbers can be changed as follows. You can also set the width, i.e. the minimum number of spaces used to print the next. These featuers are used, for example, to make output items line up in columns when printed. Both of these features require that you include the iomanip header file.

cout << setprecision(2); \\ print two digits after decimal point cout.precision(2); \\ an alternative syntax

Page 150: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

150 [email protected]

cout << setw(8); \\ make item occupy 8 characters cout.width(8); \\ an alternative syntax

Setting the width to k forces the item to occupy at least k characters. If its printed representation is shorter, blanks will be added so that it occupies k characters. If its printed representation is longer, it will occupy more than k characters.

When you reset parameters such as the precision, it is not clear whether the new value lasts only for the next item printed or whether it persists for subsequent values. Apparently this varies with the parameter and the C++ compiler. Therefore, if you care about the value of some formatting parameter, explicitly set it to the right thing before you output each item.

Repositioning and error states

In general, it is possible to move to any position in a file stream. This is a capability most programmers use rarely, if at all. For fairly obvious reasons, don't try to use repositioning operations on the standard input, output, or error streams.

The most likely reason for using a repositioning command is to rewind a file to the start, so that you can read its contents again. This is done as follows:

fp_in.clear(); // forget we hit the end of file fp_in.seekg(0, ios::beg); // move to the start of the file

Data Conversion

The following functions convert data types:

atof() converts an ASCII character to a double (to float in c++) atoi() converts an ASCII character to an integer atol() converts an ASCII to a long integer itoa() converts an integer to a character array

Example:

/* convert a string to an integer */

#include <stdio.h> #include <stdlib.h> char string[] = “1234”;

Page 151: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

151 [email protected]

int main(void) { int sum; sum = atoi( string); printf(“Sum = %d\n”, sum); return 0; } Another example: /* convert a string to an integer */ #include <stdio.h> #include <stdlib.h> int main(void) // remember that the default return data is int { int sum; char buff[20]; printf(“Enter in an integer “); scanf (“%d”, &sum); printf(“As a string it is %s\n”, itoa(sum, buff, 10)); return 0; }

Note that itoa() takes three parameters: • The integer to be converted • A character buffer into which the resultant string is stored • A radix value (10=decimal, 16=hexadecimal);

Built in functions for character handling

The following character handling functions are defined in ctype.h

isalnum tests for alphanumeric character isalpha tests for alphabetic character isascii tests for ASCII character iscntrl tests for control character isdigit tests for 0 to 9 isgraph tests for printable character islower tests for lowercase isprint tests for printable character ispunct tests for punctuation character isspace tests for space character isupper tests for uppercase character isxdigit tests for hexadecimal toascii converts character to ASCII code tolower converts character to lowercase toupper converts a character to uppercase

Page 152: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

152 [email protected]

To convert a string array to uppercase one character at a time using touper()

#include <stdio.h> #include <ctype.h> int main(void) { char name[80]; int loop; printf(“Enter in a name in lowercase\n”); scanf(“%s”, &name); for (loop = 0; name[loop] !=0; loop++) name[loop] = toupper(name[loop]); printf(“The name in uppercase is |%s\n”, name); return 0; }

Sample program output

Enter in a name in lowercase samuel The name In uppercase in SAMUEL

Don't worry if this lesson seems too complicated. Pay attention only to the keywords that are summarized in the bullet points on top of this page.

A new section is under construction which will list all the standard libraries (as defined by ASCII) and will sort all keywords alphabetically and by library.

Pointers

What is a Pointer?

So what is a pointer? A pointer is a way to get at another object. Essentially it is a way to grab an instance of an object and then either pass that instance a message or retreive some data from that object. A pointer is actually just an address of where an instance is held in memory.

Some piece of your program can either possess an instance of an object, or know where an instance of an object is. An instance of an object is a chunk of memory that is big enough to store all the member data of that object. A pointer is an address that explains how to get to where the instance is actually held in memory. Here's a quick example:

Our Player object has three pieces of data that it owns: strength, agility, and health. These are a part of the player object. That makes sense in real world terms. The player knows about two

Page 153: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

153 [email protected]

other pieces of data: the weapon and the armor that the player possesses. Here's a diagram for an instance of the player object.

So that is how to conceptually think of pointers. Now what's really going on? Memory in a computer is a complicated thing, but let's reduce it to it's simplest form: one large string of slots with addresses that data can be put in. As in the following picture:

If we were to access the spot in memory with address 3, we would get the value 45. If we were to access the spot in memory with address 2 we would get the value "Dave". The previous diagram over simplifies two important concepts, however. First, each spot that has an address is the same size as every other spot. Second, what's held in memory is simply data. That is, the information there is just a string of binary data, 1's and 0's. The way that the data is viewed gives it meaning.

With these new ideas in mind let's Take a look at our previous diagram about the player and see what's really going on. Here is the pseudo code for the Player in a little more detail than we have seen:

class Player { // attributes int health; int strength; int agility; // pointers to weapons and armor Pointer weapon; Pointer armor;

Page 154: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

154 [email protected]

// actions that a player knows how to perform void move(); void attackMonster(); void getTreasure(); };

What follows could be a view of memory. This will seem fairly complex and is not imperative to understanding the c++ language. If it does not make sense right away, come back to it.

I have translated the actual binary values to their corresponding values in the context of our program. In this view an instance of a Player is stored at memory address 4098. The first attribute (instance variable) is there: health is 12. The second attribute is strength, 14. Then agility 16. The next attribute, stored at address 4104 is a pointer to an instance of a weapon object. If we follow that to the bottom of thediagram, there is the name of the weapon, "club" stored as ASCII values at address 6144 through address 6148 (the 0 ends the string). The next attribute for a weapon after name is rating, in this case 2, which means "poor" because I have decided that the rating system should be:

1 = very poor 2 = poor 3 = average 4 = good 5 = very good

Notice that all the memory contains is binary data. It is how that data is viewed that actually gives it meaning.

Pointers Simplified

� constant pointer � dereferencing operator � expanded memory

Page 155: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

155 [email protected]

� extended memory � pointer

What You'll Learn

• Inside memory • Pointer variables • The marriage of arrays and pointers • Pointers to characters • Arrays of pointers

Definition

Pointer variables point to other variables.

This unit takes you into the world of advanced Visual C++ programming by teaching you about pointer variables. Be warned: At first, pointer variables seem to add more work without offering any advantages. Be patient! Before this unit ends, you'll see how pointers let you write programs that manipulate string data in arrays. Until you learn about pointers, you can't keep track of string data using an array.

Pointer variables are often just called pointers.

Although pointers are considered advanced, the true power of Visual C++ doesn't appear until you master pointers. Many programming languages, such as COBOL, FORTRAN, and QBasic, don't support pointers. Those languages can't provide for the advanced data management that you'll read about in Lesson 9.

Enough convincing! Let's get to the point.

Inside Memory

To understand pointers, you must understand computer memory.

Definition

RAM stands for random access memory.

The memory inside your PC, often called RAM, holds your program, data, and operating system.

Page 156: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

156 [email protected]

There are really two types of memory if you count the disk drive. The disk, however, is long-term memory. Your PC can't process any program or data on the disk until you or another program reads the disk contents into RAM.

To keep things simple, RAM will be called memory throughout the rest of this book. ROM, a special kind of read-only memory, isn't discussed here.

Your computer can process only data stored in memory. Therefore, your computer's memory is vital and closely tied to your computer's processor. Until now, you didn't need to know much about memory to run Visual C++ programs. However, a thorough understanding of pointers isn't possible until you really understand the makeup of your computer's memory storage.

Figure 16.1 shows an overview of memory as viewed by Visual C++. When you run Windows or OS/2, you'll have to give up even more memory for your operating environment, but usually there's still enough memory left to write virtually any program you need.

Your PC's memory layout.

The Address column in Figure 16.1 is very important for this unit. Each memory location in your PC has a different address, just as your house has an address different from the rest of the world. The PC's addresses are sequential numbers that begin at 0 and increment at each memory location through the highest memory location.

When you define a variable, Visual C++ finds the next empty address in the data area and sticks the variable at that location. Visual C++ keeps track, through an internal table, of where each variable resides. As you already know, Visual C++'s data types consume different amounts of memory, so variables are rarely stored in back-to-back addresses. Integers take two bytes, long integers take four, and so on.

After the variable definitions

main() { int i = 19; char c = 'X'; float f = 3.453; }

Visual C++ would store the data in memory to look something like the memory in Figure 16.2. Of course, the variables probably wouldn't be placed exactly at the addresses in the figure, but the important thing to note is that each variable starts at a given address and different data types take different amounts of memory.

Page 157: C++ & VISUAL C++

VISUAL C++ PROGRAMMING VC++

157 [email protected]

Three defined variables in memory.

Aren't variable names great? Without variable names, you would have to remember the address of every data value your program worked with.

Each memory location in your computer contains a specific address. When you define variables, Visual C++ finds unused memory locations and stores the variables there. When you refer to a variable by name, Visual C++ finds that variable's address and works with the value stored there.

There is no Stop and Type section here due to this section's conceptual nature.