0% found this document useful (0 votes)
276 views68 pages

Microsoft Press - Visual C++.NET Step by Step PDF

This document introduces C++ programming and provides an example "Hello World" program. It discusses that C++ is a strongly typed, efficient, object-oriented language based on C. It then presents a simple C++ program that prints "Hello World" to illustrate fundamental concepts like functions, headers, and output streams. The document explains that the main function is required as the starting point for C++ programs.

Uploaded by

shit
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
276 views68 pages

Microsoft Press - Visual C++.NET Step by Step PDF

This document introduces C++ programming and provides an example "Hello World" program. It discusses that C++ is a strongly typed, efficient, object-oriented language based on C. It then presents a simple C++ program that prints "Hello World" to illustrate fundamental concepts like functions, headers, and output streams. The document explains that the main function is required as the starting point for C++ programs.

Uploaded by

shit
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 68

PART 1

Getting Started
with C++

C01615675.p65 1 12/16/01, 6:53 PM


C01615675.p65 2 12/16/01, 6:53 PM
CHAPTER 3

1
Hello, C++!
In this chapter, you’ll learn about

Hello, C++!
✔ C++ characteristics
✔ C++ functions
✔ C++ keywords and identifiers
✔ Creating a C++ program

Welcome to the exciting world of programming .NET with Microsoft Visual


C++. This chapter introduces the C++ language and simple input/output (I/O)
using the C++ standard library console (text-based) facilities.
What is a C++ program? Well, it contains exactly the same elements as any
other computer program—data to store your information and blocks of code
that manipulate that data. Whether your previous experience is with Microsoft
Visual Basic or with 40-year-old COBOL, the basic elements will be familiar.
Much mystery surrounds the practice of C++ programming, but most of it is un-
warranted and unnecessary.
Let’s start with some basic ground rules for C++:

C++ is a strongly typed language.


If you have a variable that has been declared able to store apples, you can store
only apples in it. However, this is not as grim as it sounds. C++ contains many
features for providing implicit conversions where necessary. This strong type
checking eliminates many common programming bugs because it explicitly dis-
allows any data type conversions that could result in data loss.

C01615675.p65 3 12/16/01, 6:53 PM


4 Microsoft Visual C++ .NET Step by Step

C++ is an efficient language.


If you write code that needs to execute quickly (sorting lists or performing com-
plex mathematics, for example), C++ should be your language of choice.

C++ is an object-oriented language.


Modern programmers like the many advantages of object-oriented program-
ming. (See Chapter 2 for more information on object-oriented programming.)
C++ is one of the premier languages for such use.

C++ is based on C (as you might suspect).


C is a well-established language. Although C++ includes some strange features—
specifically to maintain its compatibility with C—it probably wouldn’t be as
popular as it is without this compatibility.

C++ is a case-sensitive language.


If the compiler warns you about an undeclared variable, you probably typed an
uppercase character instead of a lowercase character (or vice versa).

Your First C++ Program


Let’s get our hands dirty with a simple C++ program. Of course, no book on
C++ would be complete without including the clichéd “Hello, World!” program,
so let’s start with that.
#include <iostream>
using namespace std;

int main()
{
cout << “Hello, World!” << endl;
return 0;
}

This short program illustrates some fundamental C++ concepts:

■ The first line uses the directive #include to tell the C++ compiler to
copy in the file named iostream at the beginning of the program.
Why is this inclusion necessary? A golden rule of C++ is that every-
thing, must be declared before it is used, including the output stream
named cout used later in the program. (The cout output stream
causes output to go to the console.) So why not just declare cout ex-

C01615675.p65 4 12/16/01, 6:53 PM


Chapter 1 Hello, C++! 5

plicitly in this file? Since the iostream file is a separate unit, it can be

1
included in any other program, thus making it easy to reuse the dec-
larations. In a nutshell, it saves a lot of typing for the programmer.

■ The second line (using…) tells the compiler that the standard C++
library is to be used (hence the word std—an abbreviation of stan-

Hello, C++!
dard). Many different libraries could be used in a single project; the
using statement lets us tell the compiler which library we mean to
use.

■ The rest of the program is an example of a C++ function. All blocks


of code in C++ are called functions—there’s no such thing as a pro-
cedure or subroutine. Each C++ function contains the header part
(the first line of this program) and function body (all the text be-
tween the braces { and }). The header part shows the return value of
the function (in this case int, short for integer), the name of the func-
tion (main), and the list of parameters inside round brackets. This
example has no parameters, so the round brackets are empty—but
the brackets still must be there.
■ All statements in C++ are terminated with a semicolon.

Of the seven lines of text in the example program, only two contain C++ state-
ments: the cout line and the return line. The cout line outputs characters to the
console. The syntax for using cout is the word cout followed by a << operator,
followed by the items you want to output. (The endl stream manipulation op-
erator inserts a new-line character in the stream.)
You can output many items by using a single cout statement—just separate any
extra items with further << operators, as shown here:
cout << “Hello” << “, “ << “World” << endl;

Alternatively, you can use several cout statements to give exactly the same effect:
cout << “Hello”;
cout << “, “;
cout << “World”;
cout << endl;

As you might expect, programmers tend to prefer the single-statement version.

C01615675.p65 5 12/16/01, 6:53 PM


6 Microsoft Visual C++ .NET Step by Step

The main Function


Why is this example’s only function named main? The simple answer is that the
example won’t compile if the function isn’t named main. However, it might be
more useful to explain how the language works.
A normal C++ program contains many functions (and also many classes—see
Chapter 2). How does the compiler know which function should be called first?
Obviously, the compiler can’t be allowed to just randomly choose a function!
The rule is that the compiler will always generate code that looks for a function
named main. If you omit the main function, the compiler reports an error and
doesn’t create a finished executable program.

Free-Format Languages
The C++ language is freeformat, which means that the compiler ignores all
spaces, carriage returns, new-line characters, tabs, form feeds, and so on.
Collectively these characters are referred to as white space. The only time
the compiler recognizes white space is if it occurs inside a string.
Free-format languages give the programmer great scope for using tab or
space indenting as a way of organizing program layout. Statements inside
a block of code—such as a for loop or an if statement—are typically in-
dented slightly (often four characters). This indentation helps the
programmer’s eye more easily pick out the contents of the block.
This gives rise to one of the most common (and least useful) arguments in
the C++ community—how do you indent the braces? Should they be in-
dented with the code or should they be left hanging at the beginning of the
if or the for statement? There is no right or wrong answer to this question
(although some hardened C++ developers might disagree), but a consistent
use of either style will help make your program readable. As far as the
compiler is concerned, your entire program could be written on one line!

So the compiler will expect a function named main. Is that all there is to it?
Well, not quite. There are some additional items—such as the return type and
parameters being correct—but in the case of main some of the C++ rules are re-
laxed. In particular, main can take parameters that represent the command-line
arguments, but you can omit them if you don’t want to use the command line.

C01615675.p65 6 12/16/01, 6:53 PM


Chapter 1 Hello, C++! 7

1
C++ Keywords and Identifiers
A C++ keyword (also called a reserved word) is a special item of text that the
compiler expects to be used in a particular way. The keywords used in the ex-
ample program are using, namespace, and return. You’re not allowed to use
these keywords as variable or function names—the compiler would report an

Hello, C++!
error if you did so.
An identifier is any name that the programmer uses to represent variables and
functions. An identifier must start with a letter and must contain only letters,
numbers, or underscores. The following are legal C++ identifiers:

■ My_variable
■ AReallyLongName

The following are not legal C++ identifiers:

Identifier Reason for being invalid


0800Number Must not start with a number
You+Me Must contain only letters, numbers, and underscores
return Must not be a reserved word

Compiler Error or Linker Error?


To be absolutely correct, it is the linker that reports the error. You’ll find
more on compiler and linker errors later in this chapter.

Outside of these restrictions, any identifier will work. (Oddly enough, the identi-
fier main is not a reserved keyword; you can define a variable named main
within the program—but this is not recommended!) Some choices are not rec-
ommended. For example:

Identifier Reason it’s not recommended

main Could be confused with the function main


INT Too close to the reserved word int
B4ugotxtme Just too cryptic!
_identifier1 An underscore at the beginning is possible but not
recommended

C01615675.p65 7 12/16/01, 6:53 PM


8 Microsoft Visual C++ .NET Step by Step

Creating an Executable Program—Theory


Several stages are required to build an executable program; Microsoft Visual
Studio .NET helps by automating them. To examine and understand these
stages, however, let’s look at them briefly. You’ll see these stages again later in
the chapter when we build our first program.

Editing the Program Source Files


Before you can create a program, you must write something! Visual Studio .NET
provides an integrated C++ editor, complete with color syntax highlighting and
IntelliSense to show function parameter information and word completion.

Compiling the Source Files


The C++ compiler is the tool for converting textual source files into machine
code object files that have an .obj file extension. (Object in this sense is not to
be confused with object–oriented.) The compiler is invoked inside the Visual
Studio .NET environment, and any errors or warnings are displayed in the envi-
ronment.
The object files produced, however, are not executable files. They are incom-
plete, lacking references to any functions not contained with the source files for
the particular compilation.

Linking the Object Files


The final step in producing an executable file is to link together all object files
that make up a particular project. This linking includes not only object files pro-
duced from your own source code, but also object files from system libraries
such as the C++ standard library or the Microsoft Foundation Class (MFC) li-
brary.
Link errors tend to be less helpful than compile errors. Compile errors will give
the file name and the line number of the error; the linker will give only the name
of the object file, so a bit of detective work is often required.

System and Class Libraries


System and class libraries often have many .obj files associated with them.
Handling all of a library’s object files in a project would soon become oner-
ous, so .obj files are frequently combined into .lib library files for conve-
nience.

C01615675.p65 8 12/16/01, 6:53 PM


Chapter 1 Hello, C++! 9

1
Running and Testing the Program
Although linking might be the final step in creating an executable file, it’s not
the last step in development. You still need to test and run the program.
For many development environments, this is often the most difficult part of the
program development cycle. However, Visual Studio .NET has yet another ace

Hello, C++!
up its sleeve—the integrated debugger. The debugger has a rich set of features to
allow easy run-time debugging, such as setting breakpoints and variable
watches.

Creating an Executable Program—Practice


● Start up Microsoft Visual Studio .NET. An invitingly blank window should be
displayed.

This window is the powerful Visual Studio .NET integrated development en-
vironment (IDE). It contains all the tools you’ll need to create full-featured,
easy-to-use applications.

Creating a Project
The first task is to create a new project for the “Hello, World!” program. To
create a project, follow these steps:
1 Under the File menu, click New, and then click Project. (Alternatively, you
can press Ctrl+Shift+N.)
The New Project dialog box will be displayed.

C01615675.p65 9 12/16/01, 6:53 PM


10 Microsoft Visual C++ .NET Step by Step

2 Select Visual C++ in the Project Types box, select Win32 Project in the Tem-
plates box, and then type HelloWorld in the Name box.
3 Choose a location for your new project in the Location box, either by typing
a directory path in the Location box, or by clicking Browse and navigating
to the appropriate directory.
4 Click OK to start the Win32 Application Wizard.

For this project, you need to create a console project. This simple, text-based in-
terface (similar to an MS-DOS screen from years ago) will be adequate for our
purposes. Unfortunately, the wizard quite reasonably assumes that you want to
create a Windows program, so you must change the default wizard settings.
1 Click on Application Settings text just underneath the Overview text.
The right side of the dialog box changes to show the current wizard set-
tings.

C01615675.p65 10 12/16/01, 6:53 PM


Chapter 1 Hello, C++! 11

1
2 Under Application Type, select Console Application, and then select Empty
Project under Additional Options.
3 Click Finish to create the project.
The wizard correctly initializes all the compiler settings for a console project.
If you’re not sure this has actually happened, right-click the HelloWorld icon

Hello, C++!
in Solution Explorer and select Properties on the shortcut menu. (Press
Ctrl+R or select Solution Explorer from the View menu if you don’t see So-
lution Explorer.)

Click the Linker folder in the left list box, click the System category, and
then examine the Configuration Properties in the right box. You will see
that the SubSystem property has been set to console.

C01615675.p65 11 12/16/01, 6:53 PM


12 Microsoft Visual C++ .NET Step by Step

Adding a C++ Source File to the Project


An empty project is not particularly exciting on its own, so let’s add a new C++
source file. As always in Visual Studio .NET, you have many ways to do the
same thing.
1 Either click the Add New Item icon or right-click the HelloWorld icon in So-
lution Explorer.

2 Click Add, and then click Add New Item to open the Add New Item dialog
box.

C01615675.p65 12 12/16/01, 6:53 PM


Chapter 1 Hello, C++! 13

1
3 Select C++ File (.cpp) from the Templates list on the right, type
HelloWorld.cpp in the Name box, and then click Open.
Visual Studio .NET creates an empty source code file and adds it to the
project for you.

Now it’s time to put the mouse down, pick up the keyboard, and start typing

Hello, C++!
some C++ code.

Adding C++ Code to the Source File


● Type in the source code for the program, as shown here.

Notice that the keywords automatically turn blue (providing you spell them
correctly).

Building the Executable


The next step is to build the executable. The term build in Visual Studio .NET
refers to compiling and linking the program. Visual Studio .NET compiles any
source files that have changed since the last build and—if no compile errors
were generated—performs a link.
● To build the executable, select Build from the Build menu or press
Ctrl+Shift+B. An Output window displaying the build progress will appear
near the bottom of the Visual Studio .NET. If no errors are encountered, the
message Build: 1 succeeded, 0 failed, 0 skipped should appear in the Out-
put window.

C01615675.p65 13 12/16/01, 6:53 PM


14 Microsoft Visual C++ .NET Step by Step

If any problems occurr, the Output Window will contain a list of errors and
warnings, as shown here.

If the error or warning is generated by the compiler and not the linker,
double-click on the error line in the Output window to place the cursor at
the line in the source file where the compiler encountered the error. Fix the
error (you might have misspelled a keyword or forgotten a semicolon), and
rebuild the project.

How Should You Treat Warnings?


Always treat warnings as errors—in other words, get rid of them. Warn-
ings are there for a reason—they mean your code is not correct.

Executing the Program


Once you’ve eliminated all errors and you’ve successfully built the project, you
can finally execute the program. Choose Start from the Debug menu to run the
program. You’ll probably be disappointed with the result, however. Your pro-
gram seems to run, but flashes into and then out of existence too quickly to see.
Why is this? You haven’t put any code in the program to pause execution. To fix
the problem, add the following line before the return statement:
cin.ignore();

C01615675.p65 14 12/16/01, 6:53 PM


Chapter 1 Hello, C++! 15

Build the program and run it again. Now you will see the output of your pro-

1
gram, paused in all its glory, waiting for you to press Enter.

Conclusion
Although the example in this chapter isn’t the most exciting program ever writ-

Hello, C++!
ten, it demonstrated some key C++ development points. It introduced the IDE,
the ability to compile and link a program, and served as an introduction to the
C++ language.
Now there’s no turning back. Every new C++ and Visual Studio .NET feature
that you learn about will fire your imagination to learn more and be productive.
Software development can be an exciting world.
Finally, don’t forget to have some fun. Go back and try a few variations on the
example program, click a few menus, and become familiar with the environ-
ment. You have nothing to lose.

Chapter 1 Quick Reference


To Do this

Create a new project in Use the File, New, Project menu item; or
Visual Studio .NET press Ctrl+Shift+N.
Add a file to a project Use the File, New, File menu item; or
press Ctrl+N.
Build a Visual Studio .NET Use the Build, Build menu item; or press
project Ctrl+Shift+B.
Execute a program from Use the Debug, Start Without Debugging
withinVisual Studio .NET menu item; or press Ctrl+F5.

C01615675.p65 15 12/16/01, 6:53 PM


C01615675.p65 16 12/16/01, 6:53 PM
CHAPTER 17

2
Introducing Object-
Oriented Programming
In this chapter, you’ll learn

Introducing OOP
✔ The key concepts of object-oriented programming
✔ How these concepts are supported by C++ language constructs
✔ About the major development benefits of object-oriented pro-
gramming
✔ How to create and use simple classes

What is Object-Oriented Programming?


Object-oriented programming (OOP) has the advantage of being a natural para-
digm in which to develop systems. We perceive the world as consisting of ob-
jects: tables, chairs, computers, cars, bank accounts, rugby matches, and
overdrafts. It is also a natural human trait to try and organize these objects, ar-
ranging them into some form of classification, choosing to highlight certain fea-
tures of objects in preference to others. So dogs and cats are mammals, toasters
and refrigerators are appliances, rugby and tennis are sports, Jaguars and Fords
are cars, trucks and cars are vehicles, and so on.
There can be many levels to these categories, and many ways to classify the ob-
jects in the world. How people classify things depends to a large extent on what
they want to do with them and the features that are salient to these desires. For
example, an electrical engineer is likely to have different, and in some ways
deeper and richer, categories for household appliances than a teacher might
have. While grouping objects into classification schemes, we also tend to high-

C02615675.p65 17 12/19/01, 11:09 AM


18 Microsoft Visual C++ .NET Step by Step

light certain attributes of objects in preference to others. For example, a car’s


color might not matter in an engineer’s mind, but it might figure heavily in a
Ferrari salesperson’s mental model of car classifications.
This idea (of building hierarchies of related objects) is used in object-oriented
programming. As long ago as the 1960s, researchers realized that many com-
puter program model entities can be named and their properties and behavior
can be described. They noticed that programs deal with bank accounts, arrays,
files, and users, which are analogous to objects in the real world.
Object-oriented development can crudely be characterized as identifying the rel-
evant objects, organizing them into hierarchies, adding the attributes to the ob-
jects that describe the relevant features in the problem context, and adding the
functions (methods) to the objects to perform the required tasks on the object.
The details are a little more complicated, but essentially it is a simple and natu-
ral process.
Yet simple and natural doesn’t necessarily mean easy, because a collection of ob-
jects could be classified in virtually countless ways. The ability to identify the
important attributes of objects and to form good abstractions and appropriate
hierarchies is key. Even within the context of a problem domain, it’s sometimes
hard to determine the correct levels of abstraction and suitable classification hi-
erarchies. Just deciding which class or grouping an object belongs to can be very
difficult. As Wittgenstein (1953) pointed out, some objects will bear more of a
family resemblance to a concept than others; for example, rugby and tennis are
more obviously sports than chess and synchronized swimming.

Features of Object-Oriented Programming


Languages
I’ve already said that object-oriented development means defining and building
hierarchies of objects, and defining their properties and behavior. You can do
this to a certain extent in any programming language, just the same as you
could, theoretically, take a trip across the Rockies in a golf cart, but it is much
easier to do object-oriented programming if you use a language that is designed
to support object-oriented programming methods.
Object-oriented programming languages—such as C++ and C#—are character-
ized by three key features—encapsulation, inheritance, and polymorphism—that
support this natural process of identifying and classifying objects.

C02615675.p65 18 12/19/01, 11:09 AM


Chapter 2 Introducing Object-Oriented Programming 19

Encapsulation
One of the problems faced by software developers is that the systems we are de-
veloping are getting increasingly larger and increasingly more complex. Encap-

2
sulation helps by breaking a program down into small, self-contained entities.
For example, if you’re building an accounting system, you’ll probably need ob-
jects to represent accounts and invoices. Once you’ve developed the Account
class, you no longer need to worry about the details of the implementation of

Introducing OOP
the class. You can use the class anywhere in your program in much the same
way you would use a built-in type, such as integer. The class will expose the es-
sential features of the Account object while hiding the implementation details.
The account’s name and the state of its balance are some of the attributes of the
object the client is interested in and needs to know. Details of how the account
name is stored—whether an array of 50 characters or a string object, or the fact
that the account’s balance is maintained as a currency variable—are irrelevant to
the client. The process of hiding the data structures and implementation details
of an object from other objects in the system is called data hiding, and it pre-
vents the other objects from accessing details they don’t need to know about.
Encapsulation makes large programs easier to comprehend; data hiding makes
them more robust.
Objects can interact with other objects only through the publicly exposed at-
tributes and methods of the object. The more attributes and methods publicly
exposed, the more difficult it will be to modify the class without affecting the
code that uses the class. A hidden variable could be changed from a long to a
double, without affecting the code that uses objects created (instantiated) from
that class. The programmer would have to worry only about the methods in the
class that accessed that variable, rather than worrying about all the places in the
program that an object instantiated from that class might be called. Chapter 6
covers the details of how C++ supports encapsulation.

Inheritance
The natural tendency for humans to classify objects into hierarchies is useful
from a programmer’s perspective and is supported in most object-oriented lan-
guages, including C++, by inheritance.
Inheritance provides two advantages to the C++ programmer. First, and most
important, it lets them build hierarchies that express the relationships between
types. Suppose that you have two classes, SavingsAccount and CheckAccount,
both of which are derived from the parent Account class. If you have a function
that requires an Account as an argument, you can pass it a SavingsAccount or a
CheckAccount, because both classes are types of Account. Account is a general
classification, and CheckAccount and SavingsAccount are more specific types.

C02615675.p65 19 12/19/01, 11:09 AM


20 Microsoft Visual C++ .NET Step by Step

The second feature is that classes can inherit features from the more general fea-
tures of classes higher in the hierarchy. Instead of developing new classes from
scratch, new classes can inherit the functionality of existing classes and then
modify or extend this functionality. The parent class from which the new class
inherits is known as the base class and the new class is known as the derived
class.
One of the major tasks facing a developer is finding appropriate classifications
for the objects and classes for their program. For example, if you need to de-
velop classes for a driving game, it makes more sense for you to develop a gen-
eral car class and then use this class as a base class for specific car types such as
Jaguar or Ford. These derived classes would then extend or modify the general
car class by adding new attributes and methods or by overriding existing meth-
ods. Decomposing objects into sub-objects—for example, a car consists of an
engine and a chassis—simplifies the development effort. As a result, each of the
objects is simpler and therefore easier to design and implement than the collec-
tive whole. Chapter 7 covers inheritance in more depth.

Polymorphism
The third feature of object-oriented programming languages is polymorphism,
which is Greek for “many forms.” It is quite a hard concept to define, so I’ll use
some examples to show you what polymorphism is, and leave the precise defini-
tions to more academic writers.
Polymorphism essentially means that classes can have the same behavior, but
implement it in different ways. Consider several different types of vehicle: they
all need to be started, so in programming terms we could say that all vehicles
have “start” functionality. Exactly how starting is implemented depends on the
vehicle: if it is a Model T Ford, it’ll mean cranking the starting handle, but if it is
a modern car, it’ll mean turning the key in the ignition, and if it is a steam loco-
motive, it’ll be a very different and more complex process.
As another example, consider the SavingsAccount and CheckAccount types I
mentioned earlier. All types derived from Account share certain functionality,
such as the ability to deposit, withdraw, and query the balance. They might
implement them in different ways, because CheckAccount might permit an over-
draft while SavingsAccount might give interest, but they all work the same way.
This means that if I’m passed an Account, it doesn’t matter exactly what type of
account it is, I can still deposit funds, withdraw funds, and query the balance.
This is useful in programming terms, because it gives you the ability to work
with generic object types—accounts and vehicles—when you’re not concerned
with the way in which each class implements functionality.

C02615675.p65 20 12/19/01, 11:09 AM


Chapter 2 Introducing Object-Oriented Programming 21

Classes and Objects


Up to this point in the chapter, the terms “class” and “object” have been used

2
fairly interchangeably. However, classes and objects aren’t the same thing, and
we need to clarify the differences between these terms. As the name implies, ob-
ject-oriented programming is about objects. An object is composed of data that
describes the object and the operations that can be performed on the object.

Introducing OOP
However, when you create a program in C++, you declare and define classes, not
objects.
A class is a user-defined type; it encapsulates both the data and the methods that
work on that data. With the exception of static functions, you cannot use classes
directly. A class is much more like a template, which is used to create (instanti-
ate) objects. Just as you have to declare an integer variable before you can use it,
you also have to instantiate an object of the class before it can be used.
For example, you would not declare and define an animal object. Instead, you
would declare and define an animal class and its attributes and methods. The
class represents the concept, so that the Animal class does not represent a spe-
cific animal but the class of all animals. When you want to use an Animal ob-
ject, you have to instantiate an animal object from the class. The class can be
considered as the abstract representation of an entity, while the instantiation of
the class—the object—is the concrete representation.

The Benefits of Object-Oriented Programming


to the Developmental Life Cycle
There are three key benefits to object-oriented programming: comprehensibility,
reusability, and extensibility. Breaking code down into classes helps to impose a
structure as programs get larger and larger. The ideal is to assemble
object-oriented systems from prewritten classes, and to make the required modi-
fications to support the new requirements by using inheritance to derive new
classes from the existing classes. The existing classes are used as building blocks
and not altered in any way. Creating systems from reusable components natu-
rally leads to higher productivity, which is probably the most frequently cited
benefit of object-oriented approaches Object-oriented development should also
result in higher quality systems. Classes that are being reused—having been
tested and developed on earlier projects—are likely to contain fewer bugs than
classes developed from scratch. Over the passage of time, bugs have been found
and fixed in these classes, whereas a class that starts from scratch has yet to pass
through the same bug detection and fixing process.

C02615675.p65 21 12/19/01, 11:09 AM


22 Microsoft Visual C++ .NET Step by Step

The features of object-oriented programming also provide benefits. Encapsula-


tion makes it easier to scale up from small systems to large systems. To a large
extent, regardless of the size of the system, the developer is simply creating ob-
jects. Large systems might require more objects than small systems, but the level
of complexity facing the developer is not significantly increased. Inheritance
helps to improve the flexibility and extensibility of systems, hence reducing their
costs to maintain. Deriving new classes from existing classes provides additional
functionality, and allows the extension of the software without altering the ex-
isting classes.
Finally, data hiding also leads to more secure systems. The state of an object can
be modified only by its publicly exposed methods; this increases the predictabil-
ity of object behavior.

A Simple Example
This example will show you how to:

■ Create a class
■ Instantiate objects from the class
■ Access member functions and attributes of the class

1 Start Microsoft Visual Studio .NET.


2 From the File menu, select New, and then select Project.
The New Project dialog box appears.
3 Set the Project Type to Visual C++ Projects.
4 Set the Template to Managed C++ Application.
5 Type animals in the Name text box.
6 Set the Location to C:\Projects. Click OK.

C02615675.p65 22 12/19/01, 11:09 AM


Chapter 2 Introducing Object-Oriented Programming 23

2
Introducing OOP
7 In the Solution Explorer window, double-click on the animals.cpp file in the
Source Files folder.
8 Add the following line immediately after the #include <stdafx.h> line at the
top of the file:
#include <string.h>
This includes the definitions that you need in order to be able to use the
string data type.
9 Immediately under the using namespace System; line, add the following
class definition:
__gc class animal
{
int legs;
String *strName;
};
To declare a class in C++, you use the keyword class followed by a name for
the class, such as “animal” in this example, then list of all the class’s mem-
ber variables, functions, and methods between an opening brace ({) and a
closing brace (}).
So far, you have created an animal class with an integer variable for the
number of its legs and a string variable for its name. As it stands, no other
program or class will be able to access these variables. The members of a
class—data and methods—are private by default and can only be accessed
by methods of the class itself. C++ provides three access modifiers—public:,
private:, and protected—to specify the visibility of the various members of
the class.

C02615675.p65 23 12/19/01, 11:09 AM


24 Microsoft Visual C++ .NET Step by Step

10 Add the keyword public: on a new line between the opening brace and the
first variable declaration.
__gc class animal
{
public:
int legs;
String *strName;
};
This makes both the variables accessible. However, it is not usually a good
idea to allow other classes and parts of your program access to the variables
of a class. As discussed above in the section on encapsulation, it is better to
keep the implementation details of a class hidden from users of that class
and to control the access to the class’s data through functions. In this ex-
ample, the keyword private: will be used to prevent direct access to the
String variable of the class. The integer variable legs will be left with public
access, simply to show how it can then be directly accessed by the main
program.
11 Add the keyword private: between the first integer variable and the second
String variable.
__gc class animal
{
public:
int legs;
private:
String *strName;
};
To provide access to the private String variable, public accessor functions
and methods need to be added to the class to allow other functions to ma-
nipulate its value.
12 After the declaration of the integer variable and before the private access
modifier, add the following method declarations or implementations lines:
void SetName(String *Name)
{ strName->Copy(Name); };
String* GetName() { return strName; };
Because these methods are small functions, it was easiest to declare and
implement them as in-line functions.
The animal class is now complete. The syntax of the declaration is:
class classname
{

C02615675.p65 24 12/19/01, 11:09 AM


Chapter 2 Introducing Object-Oriented Programming 25

Access control keywords (Public: Private: or Protected:)


The declaration of class variables and methods
}

2
You have probably noticed the __gc keyword. This is one of the Managed Ex-
tensions for C++ that simplifies the interaction with .NET Framework compo-
nents. By placing __gc in front of the class keyword, the class becomes a
managed class. When the object is instantiated, it will be created on the common

Introducing OOP
language run-time heap, and the new operator will return the memory address
of this object. The lifetime of an object instantiated from the class will be man-
aged by the .NET developer platform. When the object falls out of scope, the
memory used will be garbage-collected, and no explicit calls to delete will have
to be made. This is a reference type variable because the variable does not actu-
ally contain the object but a pointer to the memory where the object is.
However, there are performance issues to consider when using reference types.
The memory has to be allocated from the managed heap, which could force a
garbage collection to occur. In addition, reference types have to be accessed via
their pointers, affecting both the size and speed of the compiled application.
Because of this, .NET also supports value types. Value type objects are created
on the stack. The variable contains the object itself rather than a pointer to the
object. Hence, the variable does not have to be dereferenced to manipulate the
object and that, of course, improves performance. To declare a value type class,
the __value keyword should be used instead of the __gc keyword. In this case,
the variables would have been created on the stack. Instead of declaring pointers
for this class and then creating the objects on the Common Language Runtime
heap by using the new operator, the objects would have been declared in the
same way as the built-in C++ types and the member variables accessed by the
dot operator rather than via the dereferencing operator.
Now that the animal class has been constructed, it can be used by the program
just as the program would use a built-in type.
1 In the main function, delete the following line:
Console::WriteLine(S”Hello World”);
2 Declare and create two animal objects in your main function:
animal *Cat, *Dog;
Cat = new animal;
Dog = new animal;
The keyword new, followed by the class of the object being created, creates
the object on the Common Language Runtime heap rather than the stack.
The memory address of the created object is returned and stored in the

C02615675.p65 25 12/19/01, 11:09 AM


26 Microsoft Visual C++ .NET Step by Step

pointer.
3 Use the member function to assign the names “Cat” and “Dog” to the re-
spective Cat and Dog objects and set the legs variable for both objects to 4.
Cat->SetName(“Cat”);
Cat->legs = 4;
Dog->SetName(“Dog”);
Dog->legs = 4;
To access the member variables and functions, you have to dereference the
pointer either by using the dereferencing operator, an asterisk (*) followed
by the dot notation—for example, (*Cat).legs—or by the shorthand opera-
tor for indirect access, a minus sign and right angle bracket (->).
4 Having created a couple of animal objects and assigned data to them, you
are now going to display that data on the screen. Add the following lines:
Console::WriteLine(“Animal 1”);
Console::Write(“Name: “);
Console::WriteLine(Cat->GetName());
Console::Write(“Legs: “);
Console::WriteLine(Cat->legs);
Console::WriteLine();
Console::WriteLine(“Animal 2”);
Console::Write(“Name: “);
Console::WriteLine(Dog->GetName());
Console::Write(“Legs: “);
Console::WriteLine(Dog->legs);
Console::WriteLine();

5 Build the application. Select Build from the Build menu bar or use the key-
board shortcut Ctrl+Shift+B.
In case you’ve had any problems putting the program together from the
fragments in the preceding steps, the entire program is listed here:
// This is the main project file for VC++ application
// project generated using an Application Wizard.

#include “stdafx.h”
#include <string.h>

#using <mscorlib.dll>
#include <tchar.h>

using namespace System;

C02615675.p65 26 12/19/01, 11:09 AM


Chapter 2 Introducing Object-Oriented Programming 27

__gc class animal


{
public:

2
int legs;

void SetName(String *Name)


{ strName = strName->Copy(Name); };

Introducing OOP
String* GetName() { return strName; };
private:
String *strName;
};

// This is the entry point for this application


int _tmain(void)
{
// TODO: Please replace the sample code below with
// your own.
animal *Cat, *Dog;

Cat = new animal;


Dog = new animal;

Cat->SetName(“Cat”);
Cat->legs = 4;
Dog->SetName(“Dog”);
Dog->legs = 4;

Console::WriteLine(“Animal 1”);
Console::Write(“Name “);
Console::WriteLine(Cat->GetName());
Console::Write(“Legs “);
Console::WriteLine(Cat->legs);
Console::WriteLine();

Console::WriteLine(“Animal 2”);
Console::Write(“Name “);
Console::WriteLine(Dog->GetName());
Console::Write(“Legs “);
Console::WriteLine(Dog->legs);
Console::WriteLine();
return 0;
}

C02615675.p65 27 12/19/01, 11:09 AM


28 Microsoft Visual C++ .NET Step by Step

6 If the build was successful, run the application by selecting Debug, Start
Without Debugging or the keyboard shortcut Ctrl+F5.

Quick Reference
To Do this

Create a class Use the keyword class


Control the visibility Use the access control keywords public:,
of variables and methods private:, or protected:
Declare a reference Place the __gc keyword before the class
type class specifier
Declare a value type class Place the __value keyword before the class
specifier
Instantiate a reference Declare a pointer of the class type for
type class object the object.
Use the new keyword followed by the name of
the class to create the object on the Common
Language Runtime heap, and assign the returned
pointer to the object pointer declared above.
For example:
HeapClass *pObject1;
pObject1 = new HeapClass;
Instantiate a value type Define the object by stating its class followed
class object by the variable name for the object.
For example:
ValueClass object1;

C02615675.p65 28 12/19/01, 11:09 AM


CHAPTER 29

3
Variables and
Operators
In this chapter, you’ll learn how to
✔ Declare (create) variables

Variables and Operators


✔ Use the built-in C++ data types
✔ Create user-defined types
✔ Add member variables to a class
✔ Use the Microsoft .NET Framework String class
✔ Assign values to a variable
✔ Create expressions using the C++ operators
✔ Cast (change) the type of a variable

In the previous chapter, we looked at the advantages of object-oriented pro-


gramming and developed a simple program to illustrate the creation and use of
classes.
In this chapter, we will take a closer look at how to create and use variables, the
fundamental data types of C++, how to access and use classes from the .NET
Framework, and the creation of expressions using the C++ operators.

What Is a Variable?
Variables are locations in memory where data can be temporarily stored for use
by the program. They have a name, type, and value. The value of the variable
can be changed during the execution of the program, hence the name variable.
Before a variable can be used, it must be declared: Its type has to be specified

C03615675.p65 29 12/19/01, 10:31 AM


30 Microsoft Visual C++ .NET Step by Step

and it has to be given a name. The type of a variable defines the allowable range
of values that the type can hold and the operations that can be performed on the
variable.

The Fundamental Data Types


C++ has a built-in set of data types, as shown in the table below.

Type Description Range


bool A Boolean type which can true false
contain true or false
char A character type which can –128 127
hold ASCII values
short An integral type; stores –32,768 32,767
whole numbers unsigned—0 65,536
int An integral type; stores –2,147,483,648 2,147,483,647
whole numbers unsigned—0 4,294,967,295
long An integral type like the int, In Microsoft Visual C++, the long is
except that on many the same size as the int and therefore
compilers, it’s twice the size can only store the same size
variables
__int8 A Microsoft specific integral
type, synonymous with the
char data type
__int16 A Microsoft specific integral
type, synonymous with the
short data type
__int32 A Microsoft specific integral
type, synonymous with the int
data type
__int64 A Microsoft specific integral –9,223,372, 9,223,372,
type that stores whole numbers 036,854, 036,854,
775,808 775,807
float Stores floating point numbers, In Visual C++, the float stores up to
for example, 3.7b six decimal places
double Stores floating point numbers The double can store up to 15
like the float but with greater decimal places
precision and hence more
accuracy.
wchar_t A wide character or multibyte
character type

C03615675.p65 30 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 31

From these types built-in types, you can construct other types, as we'll see in this
and later chapters:

■ Pointer types, for example, int*


■ Array types, for example, int[]
■ Reference types, for example, double&

3
Or you can construct user-defined types by creating data structures and classes;
see the section on user-defined types below.

Variables and Operators


Declaring a Variable
As mentioned above, variables have to be declared before they can be used. A
simple declaration consists of a type, followed by one or more variable names
separated by commas and terminated by a semicolon. For example:
int nPrimeNumber;
double x, y, z;

Each variable can be given a qualifier before the type (for example, unsigned).
You can also place an initializer after the variable name in order to give it an ini-
tial value (for example, int i = 0). The qualifier and the initializer are optional
and do not have to appear in the declaration, but the base type and variable
name must be present. The declaration is terminated by the semicolon:
[qualifier] type name [initializer];

unsigned int i; // An unsigned integer variable i, note the


// qualifier limiting the variable to
// positive numbers.
long lSalary = 0; // A long variable initialized to zero.
double y; // A double variable without qualifier or
// initializer

Declaring the variable enables the compiler to:

■ Allocate enough memory to store the variable of that type and to


associate the name of the variable with that memory location.
■ Reserve the name of the variable to prevent it from being used by
other variables within the same function.
■ Ensure that the variable is used in a way consistent with its type. For
example, if you have declared a variable as a char, you can’t store
the value 3.7 in it.

C03615675.p65 31 12/19/01, 10:31 AM


32 Microsoft Visual C++ .NET Step by Step

Variable Naming
A C++ variable name can be any combination of letters, numbers, and under-
scores as long as the first character of the variable is a letter or underscore. Al-
though C++ does not place any restrictions on your choice of variable names,
you should use meaningful variable names and be consistent in your naming
conventions to increase the readability of your code. C++ is case-sensitive, mean-
ing uppercase and lowercase letters are considered different; for example,
myvariable and myVariable are two separate variables. However, it’s not a good
idea to differentiate variables solely on the basis of case in order to avoid confu-
sion. It would be easy to type a letter in the wrong case and end up using a com-
pletely wrong variable!

note
Do not create identifiers that begin with two underscores or an underscore
followed by a capital letter, (for example, _A). Microsoft uses this naming con-
vention to specify macros and Microsoft-specific keywords, so starting your
variables with these combinations could lead to name conflicts.

Declaring Multiple Variables


You can declare several variables of the same type in the same statement simply
by separating them with commas:
int x = 10, y, z = 11;

This statement creates three integers called x, y, and z. The first integer is initial-
ized to 10 and the third to 11, while the second is not initialized.

Assigning Values to Variables


You assign a value to a variable by using the assignment operator = (an equal
sign). The value on the right side of the operator is stored in the variable on the
left side. When assigning a value to a variable, the value must belong to the
same type as the variable, be a type for which C++ will perform an assignment
conversion (such as between float and integral types), or be explicitly cast to the
correct type.

C03615675.p65 32 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 33

note
Assignment conversions occur when variables on opposite sides of an equal sign
are of different types, and the compiler can convert between the two types
without any possible loss of data. For instance, assigning an integer to a double
will result in an assignment conversion because all the compiler has to do is to

3
add '.0' to the integer to make the conversion.
You may occasionally need to tell the compiler to perform a conversion which
it otherwise wouldn't do. For example dividing two integers will result in an

Variables and Operators


integer result: if you want a floating point result, you can tell the compiler to
convert one of the values to a double, like this:
double result = double(640) / 480;

You give the name of the type to convert to, followed by the value in paren-
theses. This process is called casting, and it can be rather dangerous because
you're telling the compiler to apply a conversion, and you'd better be sure
you're correct:
int x;
float y;
double z;
x = 1;
z = x;
y = 3.56;
x = y; // Assignment conversion from float to int
// results in loss of data.
// The integer 3 is stored in the variable x.

The compiler will generate the warning "C4244: ‘=’ conversion from ‘float’ to
‘int’ possible loss of data." The reason for this is that the assignment to an in-
teger will lose the fractional part, so 3.56 will be truncated to 3.

Arrays
An array is a collection of data-storage locations, each of which holds the same
type of data—such as all integers or all doubles—but only one type. Arrays are
very useful when you want to represent a collection of values, such as the num-
ber of days in each month or the names of company employees. Each storage
location is called an element of the array. Elements of the array are accessed by
referring to an offset from the array name. The array elements start at zero (0)
and continue up to one less than the array bound:

C03615675.p65 33 12/19/01, 10:31 AM


34 Microsoft Visual C++ .NET Step by Step

int nArray[10]; // Declare an array of ten integers.


int x;
nArray[0] = 23; // The first element in the array starts at
// the offset 0
nArray[9] = 21; // The last element in the array starts at
// the offset 9
x = nArray[0];

Writing past the end of the array is a serious problem and the cause of many
bugs in C++ programs. When accessing an array element, the compiler calculates
the offset from the start of the array. If you’re writing to an array element and
you give an invalid index so that the calculated offset is beyond the end of the
array, the compiler will overwrite whatever happens to be in that memory loca-
tion.

Pointers
A pointer is a variable that holds the memory address of another variable or
function, and this means that you can use a pointer to refer indirectly to a vari-
able.

note
Why are pointers useful? The first, and most pragmatic reason, is that they have
been part of the C family of languages right since the start and they're very
widely used, so you'll need to know something about them. There are many
other reasons though, and I've summarized a couple of the most important ones
in this note.
First, pointers are one of the main ways that arguments are passed to functions.
Arguments are usually passed by value – as a copy – so you can't modify the
value and expect it to get back to the calling code. Pointers let you pass argu-
ments in such a way that you can modify them.
Second, some operations on series of data – such as values in arrays – can be
performed very efficiently using pointers.

Although a pointer variable contains an address and therefore can store a


memory address of any data type, pointer variables are declared to be data type
specific. A pointer to an integral data type (int) can’t store the address of a
double. The pointer variable is declared in the same way as the data type vari-
able, but the pointer operator * (an asterisk) is appended to the data type:

C03615675.p65 34 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 35

int* pi; // pointer to an int


double* pd; // pointer to a double
char* pc; // pointer to a char

Every variable has an address and that address can be obtained using the ad-
dress of operator, an ampersand (&). The address of the variable can be stored

3
in a pointer variable and using that pointer, the contents of that variable can be
manipulated by using the dereference operator * (an asterisk):

Variables and Operators


int x = 10, y = 0;
int* pX = NULL; // Declare an integer pointer.
pX = &x; // Store the address of the integer variable x.
y = *pX; // Use the dereference operator to assign the
// value of x to y.
*pX = 20; // Use the dereference operator to assign 20 to x.

In the last two lines of the code, *pX can be read as “what pX points to.” Chap-
ters 7 and 8 will discuss pointers in more detail.

References
A reference variable is an alias for another variable. All reference variables must
be initialized when declared. From then on, any changes made to the referenced
variable will be made to the aliased variable. Reference variables are particularly
important when passing variables to functions; this topic will be covered in
Chapter 4, but here’s an example:
int x = 10;
int& y = x; // declare y as reference to x.
Y = 4; // Changes the value of x to 4.

Constants
Like variables, constants are named data-storage locations. However, unlike a
variable, the value of a constant can’t be changed after it has been declared. It
has to be initialized when it is created and can’t be assigned a new value later.
C++ has two types of constants: literal and symbolic.
A literal constant is simply a value typed into the program. The statements be-
low assign the literals 40 and “Dog“ to the respective variables NoOfEmployees
and strName:
NoOfEmployees = 40;
strName = ”Dog”;

C03615675.p65 35 12/19/01, 10:31 AM


36 Microsoft Visual C++ .NET Step by Step

A symbolic constant is a constant that is represented by a name. It is defined in


exactly the same way as a variable, but the qualifier must start with the keyword
const and the variable must be initialized. After declaration, the constant name
can be used anywhere a variable of that type could be used:
const unsigned long NoOfFullTimeEmployees = 49;
const unsigned long NoOfPartTimeEmployees = 234;
unsigned int NoOfEmployees;
NoOfEmployees = NoOfFullTimeEmployees + NoOfPartTimeEmployees;

There are a couple of advantages to using symbolic constants rather than literal
ones:

■ The symbolic names make the program more readable. The sym-
bolic constant NoOfFullTimeEmployees is more meaningful than
the literal constant 49.
■ It is easier to change a single symbolic constant declaration than to
find and replace all occurrences of a literal in a program.

However, this can be taken too far. It is not necessary to replace all literals with
constants. There are some constants which are intuitively obvious to everyone
and which are not going to change; for example, the number of days in a week
or months in a year. These values can be left as literals without reducing the
readability or maintainability of the code.

Enumerations
In situations where a variable can only take on a specific set of values, such as
colors or gender, enumerations allow you to create new types and to declare
variables whose values are restricted to the enumerated set.
Enumerations are declared by the keyword enum, followed by the type name, an
opening brace ({), the enumerated values separated by commas, a closing brace
(}), and a semicolon (;). Variables are then declared as an enumerated type, and
they can only receive one of the enumerated values:
enum WorkDays { Monday, Tuesday, Wednesday, Thursday, Friday };
const int Saturday = 7;
WorkDays WorkingDay;
WorkingDay = Thursday; // Thursday is a member of the WorkDays
// enumerated type and therefore can be
// assigned to the WorkDays variable.
WorkingDay = Saturday; // Although Saturday is an integer

C03615675.p65 36 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 37

// constant, it is not part of the


// enumerated type WorkDays and
// therefore can’t be assigned to the
// WorkDays variable.

Typedefs

3
A typedef is a user-defined synonym for an existing type. To create a synonym
for a type, you use the keyword typedef followed by the name of the type and

Variables and Operators


the new name you are defining. Because typedef is a C++ statement, you also
need a closing semicolon:
typedef unsigned int positiveNumber;

The typedef above declares positiveNumber to be a synonym of unsigned int


and can be used in a declaration instead of the actual type name:
positiveNumber one, two;

Adding Member Variables to Classes


1 Start Microsoft Visual Studio .NET, and select New from the File menu, then
select Project.
The New Project dialog box appears.
2 Set the Project Type to Visual C++ Projects, and set the Template to Man-
aged C++ Application.
3 Type variables in the Name text box and set the Location to C:\Projects.
Click OK.
From the Project menu, select Add Class. The Add Class dialog box appears.
4 Set the Template to Generic C++ Class. Click Open.
The Generic C++ Class Wizard dialog box appears.
5 Type animal in the Class Name text box. Note how default names for the
header and source files are created automatically.
6 Leave the Base Class text box blank.
7 In the Access list, select Public. (Note that Public is the default so it should
already be selected.)
8 Check the Virtual Destructor check box.
(Class destructors will be explained in Chapter 7.)

C03615675.p65 37 12/19/01, 10:31 AM


38 Microsoft Visual C++ .NET Step by Step

9 Click Finish.
Note that the source code for the new class, animal.cpp, has been loaded
into the main window. In the Solution Explorer, the animal.cpp file has been
added to the Source Files folder and the header file, animal.h, has been
added to the Header Files folder. In the Class View window, if you expand
the Animals Project node, you will see that the new animal class has been
added to the project. If you expand the animal class, you will see the de-
fault constructor, animal(void), and destructor, ~animal(void), for the class.
10 In the Class View window, right-click on the animal class and select
Add, then select Add Variable.
11 Accept the default Access modifier public.
12 Select int from the Variable Type drop-down menu.
13 Type legs in the Variable name text box.

C03615675.p65 38 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 39

3
Variables and Operators
14 Click Finish.
In this exercise you've seen how to create a new class using Visual Studio
and how to add members to it.

The .NET Framework String Class


The String class is not a built-in data type like int or long, but part of the .NET
Framework. Because String isn't a built-in type, you have to include some files in
your project before the compiler will let you use it. Add the following two lines
to the top of your project:
#using <mscorlib.dll>
using namespace System;

The '#using' line tells the compiler to look in the file mscorlib.dll for details of
the String class. Mscorlib.dll is the library file that contains the core .NET com-
ponents, and you'll meet it a lot during the course of this book. The second 'us-
ing' line makes it easier to use certain .NET classes; just type the line in as it is
for now, and you'll find out more about namespaces in Chapter 15.
The String class contains a large number of methods to simplify manipulating
strings.

C03615675.p65 39 12/19/01, 10:31 AM


40 Microsoft Visual C++ .NET Step by Step

note
Although the String class is a very powerful class, once you initialize a String
object, it is immutable: it can’t be changed after it is created. The member func-
tions of the String class that appear to alter Strings, such as Insert and Replace,
actually return a new String object which contains the modification(s). This
makes these String class methods very inefficient when making repeated modi-
fications to a string. If you need to make repeated changes to a string, you
should use the StringBuilder class. You will have to include the mscorlib.dll as-
sembly and the System.Text namespace to simplify member access.

Operators And Expressions


Expressions are built using operators that work with data—the operands—to
give a result. For example:
Remuneration = Salary + Bonus;

In the above example, the addition operator + (a plus sign) is used to add the
operands Salary and Bonus, and the assignment operator is used to store the to-
tal in the Remuneration variable.

Assignment Operators
An assignment expression is used to assign a value to a variable. All expressions
return a value when evaluated and the value of the assignment expression is the
new value of the object on the left side. This makes it possible to assign the same
value to a group of variables. For example:
NoOfMammals = NoOfDogs = NoOfCats = 0;

In the above example, all three variables—NoOfMammals, NoOfDogs, and


NoOfCats—are set to zero.

Arithmetic Operators
C++ has 12 arithmetic operators, five of which operate like the standard math-
ematical operators: the addition operator + (a plus sign), the subtraction opera-
tor - (a minus sign), the multiplication operator * (an asterisk), the division
operator / (a slash), and the modulus operator % (a percentage sign), which re-
turns the remainder after division:
Result = 4 + 2 - 3; // Result = 3
Result = 4 * 5; // Result = 20
Remainder = 7 % 3; // Remainder = 1

C03615675.p65 40 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 41

In addition, there are a number of arithmetic assignment operators: the addition


assignment operator += (a plus sign with an equal sign), the subtraction assign-
ment operator -= (a minus sign with an equal sign), the multiplication assign-
ment operator *= (an asterisk with an equal sign), the division assignment
operator /= (a slash with an equal sign), and the modulus assignment operator
%= (a percentage sign with an equal sign). These operators are shorthand forms

3
that combine the corresponding mathematical operation with the assignment
operation. For example:

Variables and Operators


A = A + 5; could be expressed as A += 5;

Instead of using the addition operator to add 5 to the value of the variable A,
and then using the assignment operator to assign the new value to the variable
A, you can just use the addition assignment operator to add 5 to the value of the
variable A and assign the new value. The addition assignment operator is a
shortcut operator. There is no difference between the two statements. In both
statements, an addition is performed, followed by an assignment. The second
form is just a shorter way of expressing a frequently used statement.
The increment and decrement operators are similar shorthand operators, but
these operators only add or subtract 1 from the value of the variable:
A++; // Adds 1 to the value of the variable A.
A--; // Subtracts 1 from the value of the variable A.

There are two forms of the increment and decrement operators: the prefix form
++A or --A, and the postfix forms A++ or A--. Both forms add or subtract 1 to
the variable. In the prefix form, the mathematical operation is performed before
the variable’s role in the expression is evaluated; in the postfix form the variable
is incremented or decremented after the variable has been used in the expression.
For example:
int a , b, c;
a = b = c = 0;
b = ++a; // a = 1, b = 1
c = a++; // c = 1, a = 2

In the code fragment above, the final values of the variables are a = 2, b = 1, and
c = 1. The prefix increment operator expression added 1 to the value of a before
assigning the value of the variable a to the variable b. The postfix increment op-
erator expression assigned the value of the variable a to the variable c and then
incremented the value of the variable a by 1.

C03615675.p65 41 12/19/01, 10:31 AM


42 Microsoft Visual C++ .NET Step by Step

note
When working with objects, the prefix versions of the increment and decrement
operators are more efficient than the postfix versions because a temporary copy
of the object doesn’t have to be made for use in the expression before
incrementing or decrementing the object.

Relational and Logical Operators


Relational operators are used to compare two values or expressions, returning a
true or false value. C++ has six relational operators: the greater than operator >
(a right angle bracket), the greater than or equal operator >= (a right angle
bracket with an equal sign), the less than operator < (a left angle bracket), the
less than or equal operator <= (a left angle bracket with an equal sign), the equal
operator == (two equal signs), and the not equal operator != (an exclamation
point with an equal sign):
a > b // returns true if a is greater than b.
a >= b // returns true if a is greater than or equal to b.
a < b // returns true if a is less than b.
a <= b // returns true if a is less than or equal to b.
a == b // returns true if a is equal to b.
a != b // returns true if a is not equal to b.

A logical operator is used to relate two relational expressions. C++ has three
logical operators: the and operator && (two ampersands), the logical OR op-
erator ||, and the not operator ! (an exclamation point). The and operator relates
two expressions both of which must be true for the operator to return a true
value. The OR operator returns true if either of the two expressions evaluates to
true:
a && b // returns true if both a and b are true
(a > b) && (a < c) // returns true if a is greater than b and a
// is less than c
a || b // returns true if either a or b are true
(a > b) || (a < c) // returns true if either a is greater than b
// or a is less than c

The evaluation of a relational expression stops as soon as the logical value of


the whole expression is determined. For example, the expression expr1 &&
expr2 is true only if both expr1 and expr2 are true. If expr1 is false, then the fi-
nal value of the expression must be false, and therefore expr2 is not evaluated.

C03615675.p65 42 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 43

The not operator returns the negation of the Boolean value of its operand:
!a // If a is true the not operator will return false, if a is
// false the not operator will return true.

These operators are most often used in decision or loop structures, which will be
discussed in Chapter 5.

3
Bitwise Operators

Variables and Operators


C++ has six bitwise operators: the and operator & (an ampersand), the bitwise
OR operator |, the exclusive OR operator ^ (a caret), the complement operator
~ (a tilde), the right shift operator >> (two right angle brackets), and the left
shift operator << (two left angle brackets). These operators work on the indi-
vidual bits of the byte and can only be applied to integral operands—char, short,
int, and long. The bitwise and operator compares the bits of two operands; if
the bit in the same position for each operand is 1, the resulting bit is 1; if how-
ever either bit is zero, the resulting bit is set to zero. This operator is often used
to mask off bits.
The bitwise OR operator compares the bits of two operands: if either bit is 1,
the corresponding bit of the result is 1, and if both bits are zero, the correspond-
ing bit of the result is set to zero. The bitwise OR operator is often used to turn
bits/flags/options on.
The exclusive OR operator sets the result bit to 1, only if one of the operands
has the corresponding bit set to 1. If the corresponding bit of both operands is 1
or 0, the bit is set to 0.
The complement operator reverses the bit setting of the operand. If the bit is 1 it
is set to 0; if the bit is 0 it is set to 1.
The left shift operator moves the bit pattern of its left operand to the left by the
number of bits specified by its right operand. The bits vacated by the left shift
are filled with zeros. The right shift operator moves the bit pattern of its right
operand to the right by the number of bits specified by its right operand. If the
variable is an unsigned data type the vacated bits will be filled with zeros; if the
variable is signed the vacated bits will be filled with the sign bit:
int a;
a = 5;
a = a << 2; // The bits of a will be shifted two bits to the left
// and the value of 20 assigned to a
a = 5;
a = a >> 2; // The bits of a will be shifted two bits to the
// right and the value of 1 assigned to a

C03615675.p65 43 12/19/01, 10:31 AM


44 Microsoft Visual C++ .NET Step by Step

The Ternary Operator


The ternary operator ? (a question mark) is an inline if statement. (See Chapter
5 for more information.) The expression to the left of the ternary operator is
evaluated: If it is true, the value or expression between the ternary operator and
the colon is returned. If it is false, the value or expression after the colon is re-
turned:
int a;
bool b;
b = true;
a = b ? 1 : 2; // b is true, so a is assigned 1.
b = false;
a = b ? 1 : 2; // b is false, so a is assigned 2.

The Sizeof Operator


The sizeof operator returns the size of the C++ data type, either built-in or user-
defined in bytes. For example, sizeof(int); and sizeof(animal).

Type Casting
C++ supports the C style cast operator, where the type you wish to convert the
expression to is placed in parentheses in front of the expression; for example,
(float) 7. It also supports four new cast operators:

■ static_cast<type>
■ const_cast<type>
■ dynamic_cast<type>
■ reinterpret_cast<type>

The static_cast<type> changes the data type of the variable. For example, if an
expression needs to convert an integer into a floating point number for a calcu-
lation, the number should be cast using the static_cast<double> operator. The
dynamic_cast<type> is used to cast objects down or across the inheritance hier-
archy (covered in Chapter 7). The const_cast<type> changes the const-ness of
the variable. The reinterpret_cast<type> allows any pointer to be converted into
a pointer of another type. For example:
int a = 10;
double b;
b = (double) a; // old C style cast operator
b = static_cast<double>(a); // C++ static_cast operator

C03615675.p65 44 12/19/01, 10:31 AM


Chapter 3 Variables and Operators 45

Operator Precedence and Associativity


There are two ways in which the expression 2 + 3 * 4 could be evaluated: It
could be evaluated as (2 + 3) * 4, giving a value of 20 or it could be evaluated as
2 + (3*4), giving a value of 14.
The rules of operator precedence allow an unambiguous evaluation of expres-

3
sions. Operators higher in the hierarchy are given precedence over operators
lower in the hierarchy. Because the * operator is higher than the + operator, the
second interpretation of the above expression, 2 + (3 * 4), would be evaluated.

Variables and Operators


In situations where two operators are at the same level in the hierarchy, the or-
der of evaluation proceeds from left to right. Hence, 2 * 3 / 2 * 3 would be
evaluated as ((2 * 3) / 2) * 3 giving a value of 9. Parentheses can be used to
group operators and override the precedence hierarchy. For example, (2 * 3) /
(2* 3) giving a value of 1. Ideally, you should use parentheses even when they
are not strictly required simply to clarify your intentions. The following table
shows the hierarchy of precedence from highest to lowest. Operators in the same
row of the table share the same level of precedence.

Operator Name
:: Scope resolution
. -> [] () ++ -- Member selection, subscripting, function calls, postfix
increment, postfix decrement
sizeof() ++ -- Sizeof(), prefix increment, prefix decrement,
^ ! - + & * new complement, not, unary minus, unary plus, address of,
delete delete[] dereference, new, delete, delete[], casting operators
static_cast<type>
const_cast<type>
dynamic_cast<type>
reinterpret_cast<type>
.* ->* Pointer to member operator
*/% Multiply, divide, modulus
+- Add, subtract
>> << Right shift, left shift
< <= > >= Relational operators (inequality)
== != Equality, inequality
& Bitwise and
| Bitwise OR
&& Logical and
|| Logical OR
?: Ternary operator
= += -= *= /= % Assignment operators
= <<= >>= &= |= ^=
, Comma

C03615675.p65 45 12/19/01, 10:31 AM


46 Microsoft Visual C++ .NET Step by Step

Chapter 3 Quick Reference


To Do This

Declare a variable Specify the type followed by space(s), then the


variable name followed by a semicolon.
For example:
int number1;
long longNumber1;
Assign values to a Use the assign operator =.
variable
Group homogenous Use an array
data together
Prevent data from Make the variable a constant. For example:
being changed const int x = 10;
Restrict the values Declare an enumerated constant and declare the
a variable can accept variable to be of that type.
to a small set
Add member variables Use the Generic C++ Class Wizard.
to a class
Access a String class Use the .NET class String.
Find the size of an Use the sizeof() operator.
object or type
Convert one data type Use the static_cast<type>() operator.
to another
Override default Use parentheses to group operators.
operator precedence or
make the code more
readable

C03615675.p65 46 12/19/01, 10:31 AM


CHAPTER 47

4
Using Functions
In this chapter, you’ll learn how to

Using Functions
✔ Declare function prototypes
✔ Define function bodies
✔ Call functions
✔ Deal with local and global variable scope
✔ Define and use overloaded functions

By now, you should be fairly comfortable with basic C++ syntax. You’ve seen
how to declare variables, write statements, use operators, and perform simple
console output. However, as your programs start to get larger, you need to orga-
nize your code to cope with the growing complexity.
In this chapter, you will learn how to divide a Microsoft Visual C++ program
into functions. First, you’ll see how to declare function prototypes to introduce
the functions to the compiler. Next, you’ll see how to define function bodies to
carry out the required processing; for example, you might write a function to
calculate the expected growth on an investment, or to get the user’s password
from a Login screen. Finally, you’ll see how to call a function from elsewhere in
your program.

C04615675.p65 47 12/19/01, 10:32 AM


48 Microsoft Visual C++ .NET Step by Step

Why Use Functions?


There are many good reasons for dividing a program into functions:
■ Each function is usually quite short and discrete. It’s easier to write a
program as a series of functions because you can concentrate on one
function at a time.
■ It’s also easier to read and debug a program that contains lots of small
functions because you don’t have to remember what the whole pro-
gram is doing.
■ Functions are reusable. Once you’ve written a function, you can call it
whenever you need it in your program. This reduces coding effort, and
therefore improves developer productivity.

Declaring Function Prototypes


A function prototype is a single-line statement that introduces the name of a
function to the compiler. The prototype also indicates what types of parameters
can be passed into the function, and what type of value the function returns.

Declaring a Simple Function Prototype


The following example shows a simple function prototype:
void DisplayWelcome();

In this example, the name of the function is DisplayWelcome. The parentheses


are required to indicate that this is a function. The parentheses are empty in this
example, which means that the function doesn’t take any parameters. The void
keyword at the beginning of the function prototype indicates that the function
doesn’t return a value either—presumably, the function just displays a welcome
message on the screen.

note
Some programming languages differentiate between functions (which return
a value) and subroutines (which do not return a value). For example, Microsoft
Visual Basic .NET uses the Function keyword for functions and the Sub keyword
for subroutines. Visual C++ just has functions; use the void return type if the
function doesn’t return a value.

C04615675.p65 48 12/19/01, 10:32 AM


Chapter 4 Using Functions 49

Notice the semicolon at the end of the function prototype. This is a statement
terminator, and it marks the end of the function prototype. A function prototype
doesn’t tell you what the function does; it just tells you the function signature.
In this exercise, you will declare a simple function prototype in a Visual C++ ap-
plication. The function will not take any parameters, and will not return a value
either.
1 Start Microsoft Visual Studio .NET and open a new Managed C++ Applica-
tion project named InvestmentPlanner.

4
2 From the View menu, select the menu command Solution Explorer.
3 In Solution Explorer, double-click InvestmentPlanner.cpp to view the code in
this file.

Using Functions
4 At the top of the file, immediately under the using namespace System; line,
add the following function prototype:
void DisplayWelcome();

This is the function prototype you saw earlier. You place function prototypes
near the top of the source file, so that they are visible to the rest of the
code in the file.
5 From the Build menu, select the menu command Build to build your pro-
gram. There’s no point in running the program yet, because you haven’t
implemented or called the DisplayWelcome function You’ll do that later in
this chapter.

Declaring Parameters in a Function Prototype


Functions can take parameters to make them more generic. You must declare
the data types for these parameters in the function prototype.
In this exercise, you will declare a function prototype that uses parameters.
1 Open the Managed C++ Application project you created in the previous ex-
ercise.
2 Add the following function prototype:
void DisplayProjectedValue(double amount, int years, double
rate);

This function prototype declares a function named DisplayProjectedValue.


The function takes three parameters: a double, an int, and another double.
The compiler uses this information to ensure that the function is always
called with the correct number and types of parameters.

C04615675.p65 49 12/19/01, 10:32 AM


50 Microsoft Visual C++ .NET Step by Step

tip
Parameter names are optional in the function prototype. Strictly speaking, you
could omit the parameter names and just specify the parameter types. How-
ever, parameter names help to convey the meaning of the parameters, so it’s
good practice to use them.

3 Build your program.

Declaring the Return Type in a Function Prototype


As well as specifying input parameters for a function, you must also specify a
return type for the function. As you saw earlier, the void return type indicates
that the function does not return a value.
In this exercise, you will see how to specify a non-void return type for a func-
tion.
1 Open the Managed C++ Application project from the previous exercise.
2 Add the following function prototype:
double GetInvestmentAmount();

This function prototype declares a function named GetInvestmentAmount.


The function doesn’t take any parameters, but it returns a double.
3 Add another function prototype as follows:
int GetInvestmentPeriod(int min, int max);

This example shows how to declare a function that takes parameters and
returns a value. The GetInvestmentPeriod function takes two int param-
eters, and also returns an int.

note
The parameter types and return type are independent of each other. The fact
that the GetInvestmentPeriod parameters and return type are all int is entirely
coincidental. It’s quite easy to imagine a function whose parameter types and
return type are different.
For example:
double CalculateAverageValue(int number1, int number2);

4 Build your program.

C04615675.p65 50 12/19/01, 10:32 AM


Chapter 4 Using Functions 51

Declaring Default Values for Function Parameters


When you declare a function prototype, you can specify default values for some
or all of its parameters. This is useful for parameters that usually have the same
value each time the function is called. Specifying a default value for a function
parameter means you can omit the parameter value when you call the function;
the compiler will substitute the default value on your behalf.
In this exercise, you will define default parameters in one of the function proto-
types you declared earlier.

4
1 Open the Managed C++ Application project from the previous exercise.
2 Find the following function prototype:
int GetInvestmentPeriod(int min, int max);

Using Functions
3 Modify the function prototype as follows to define default parameter val-
ues:
int GetInvestmentPeriod(int min=10, int max=25);

This function prototype has two parameters named min and max. The pa-
rameters are followed by an = sign, then a default value. We have defined a
default value of 10 for the min parameter and a default value of 25 for the
max parameter. You’ll see how to call this function later in this chapter.
4 Build your program.

Defining Function Bodies


In the previous section, you learned how to declare function prototypes. As you
saw, a function prototype specifies the name of a function, its parameter list,
and its return type. However, function prototypes do not contain any executable
statements; they do not indicate what the function will do when it is called.
To provide the behavior for a function, you must define a function body. The
function body contains executable statements to perform the desired operations
in the function.
In this part of the chapter, you will define function bodies for all the function
prototypes introduced earlier.

Defining a Simple Function Body


The following example shows a simple function body, corresponding to the
DisplayWelcome function prototype you saw earlier:
void DisplayWelcome()

C04615675.p65 51 12/19/01, 10:32 AM


52 Microsoft Visual C++ .NET Step by Step

{
Console::WriteLine(S"---------------------------------------");
Console::WriteLine(
S"Welcome to your friendly Investment Planner");
Console::WriteLine(S"---------------------------------------");
return;
}

Notice that the first line of the function body is identical to the function proto-
type, except that there is no semicolon. This first line is known as the function
header.
After the function header, a pair of braces ({}) encloses the executable statements
for the function body. In this example, the DisplayWelcome function displays a
simple welcome message on the screen. Later in this chapter, you’ll see more
complex functions that perform Console input and mathematical calculations.
The return keyword at the end of the function causes flow of control to return
to the calling function. In this example, the return keyword is superfluous be-
cause the closing brace of the function acts as an implicit return. However, you
can use return in other locations in a function, such as within an if statement, to
return prematurely from a function. You’ll see more about the if statement in
Chapter 5.
In this exercise, you will add the DisplayWelcome function body to your Visual
C++ application.
1 Open the Managed C++ Application project you created earlier in this
chapter.
2 Locate the end of the main function. On the next line, define the
DisplayWelcome function body as follows:
void DisplayWelcome()
{
Console::WriteLine(S"--------------------------------");
Console::WriteLine(
S"Welcome to your friendly Investment Planner");
Console::WriteLine(S"---------------------------------");
return;
}

C04615675.p65 52 12/19/01, 10:32 AM


Chapter 4 Using Functions 53

3 Build your program. You shouldn’t get any compiler errors.

note
You can define function bodies in any order in Visual C++. For example, you
can place the DisplayWelcome function body before or after the main func-
tion body. However, functions cannot be nested. You can’t define one function
body inside the braces ({}) of another function.

4
Defining a Function Body that Uses Parameters
When you define a function body that uses parameters, you must define exactly

Using Functions
the same number and types of parameters as in the function prototype. This is
quite reasonable—the whole point of the function prototype is to introduce the
exact signature of the function.

tip
The function body can use different parameter names than the prototype be-
cause the parameter names in the prototype are there just for documentation.
However, for consistency, you should use the same parameter names in the
prototype and the function body.

In this exercise, you will define a function body for the DisplayProjectedValue
function. You saw the prototype for this function earlier:
void DisplayProjectedValue(double amount, int years, double rate);

The function body will have the same signature as the prototype and will calcu-
late the projected value of an investment after a specified number of years at a
particular growth rate.
1 Open the Managed C++ Application project from the previous exercise.
2 Scroll to the end of the program, and add the following code. This is the
start of the DisplayProjectedValue function body:
void DisplayProjectedValue(double amount, int years, double
rate)
{

3 Next, define some local variables within the function:

C04615675.p65 53 12/19/01, 10:32 AM


54 Microsoft Visual C++ .NET Step by Step

double rateFraction = 1 + (rate/100);


double finalAmount = amount * Math::Pow(rateFraction,
years);
finalAmount = Math::Round(finalAmount, 2);

Here, the rateFraction variable holds the growth rate as a fractional value.
For example, if the rate is 6 percent, then rateFraction will be 1.06.
The expression Math::Pow(rateFraction, years) shows how to raise a num-
ber to a power in Visual C++. For example, Math::Pow(1.06, 3) is equiva-
lent to 1.06 * 1.06 * 1.06.
The expression Math::Round(finalAmount, 2) rounds finalAmount to two
decimal places. For example, if finalAmount is 1000.775, the rounded value
will be 1000.78.
4 Now add the following statements to the function to display the result of
the calculations:
Console::Write(S"Investment amount: ");
Console::WriteLine(amount);

Console::Write(S"Growth rate [%]: ");


Console::WriteLine(rate);

Console::Write(S"Period [years]: ");


Console::WriteLine(years);

Console::Write(
S"Projected final value of investment: ");
Console::WriteLine(finalAmount);

return;
}

5 Build your program.

Defining a Function Body that Returns a Value


When you define a function with a non-void return type, you must return an ap-
propriate value from the function. To return a value, use the return keyword fol-
lowed by the value you want to return.

C04615675.p65 54 12/19/01, 10:32 AM


Chapter 4 Using Functions 55

note
If you forget to return a value, you’ll get a compiler error on the closing brace
of the function. This is the point where the compiler realizes you haven’t re-
turned a value from the function.

In this exercise, you will define a function body for the GetInvestmentAmount
function. This is the prototype for the function, as you saw earlier:

4
double GetInvestmentAmount();

The function will ask the user how much money they want to invest. The func-
tion will return this value as a double data type.

Using Functions
You will also define a function body for the GetInvestmentPeriod function. The
prototype for this function is:
int GetInvestmentPeriod(int min=10, int max=25);

The function will ask the user how long they want to invest their money and
will return this value as an int data type.
1 Open the Managed C++ Application project from the previous exercise.
2 Scroll to the end of the program, and define the GetInvestmentAmount
function body as follows:
double GetInvestmentAmount()
{
Console::Write(
S"How much money do you want to invest? ");

String __gc * input = Console::ReadLine();


double amount = input->ToDouble(0);

return amount;
}

The first statement displays a prompt message on the Console, asking the
user how much money they want to invest. The Console::ReadLine func-
tion call reads a line of text from the Console keyboard, and the result is as-
signed to a String variable. (You’ll learn what the __gc syntax means in a
later chapter.)
The input->ToDouble function call parses the string and converts it to a
double value. The return statement returns this value back to the calling
function.

C04615675.p65 55 12/19/01, 10:32 AM


56 Microsoft Visual C++ .NET Step by Step

tip
You can declare local variables anywhere in a function. For example, here
the input and amount variables are declared halfway down the
GetInvestmentAmount function. Typically, you should declare variables at the
point where they are first needed in the function. This is different from the C
programming language, where you have to declare local variables at the start
of a block.

3 Now add the following function body:


int GetInvestmentPeriod(int min, int max)
{
Console::Write(S"Over how many years [");
Console::Write(S"min=");
Console::Write(min);
Console::Write(S", max=");
Console::Write(max);
Console::Write(S"] ? ");

String __gc * input = Console::ReadLine();


int years = input->ToInt32(0);

return years;
}

The Console::Write function calls ask the user to enter a value between min
and max; these values are supplied as parameters into the
GetInvestmentPeriod function.
The Console::ReadLine function call reads the user’s input as a String, and
the input->ToInt32 function call converts this value into a 32-bit integer.
The return statement returns this value to the calling function.

note
The function prototype for GetInvestmentPeriod declared default values for the
min and max parameters. The default value for min is 10, and the default value
for max is 25. Default values are only specified in the function prototype—you
don’t mention these default values in the function body. If you accidentally
define the default values in the function body as well as in the function proto-
type, you’ll get a compiler error at the function body.

C04615675.p65 56 12/19/01, 10:32 AM


Chapter 4 Using Functions 57

4 Build your program.

Calling Functions
Now that you have defined all the function bodies in the sample application, the
last step is to call the functions at the appropriate place in the application.
To call a function, specify its name followed by a pair of parentheses. For ex-
ample, you can call the DisplayWelcome function as follows:

4
DisplayWelcome();

This is a simple example because the function doesn’t take any parameters or
return a value.

Using Functions
If you want to call a function that returns a value, you can assign the return
value to a variable. The following example calls the GetInvestmentAmount
function, and assigns the return value (a double) to a local variable named sum:
double sum = GetInvestmentAmount();

note
You can ignore the return value from a function if you want. When you call the
function, leave out the assignment operator on the left side of the function
name. The function still returns the value, but the value is discarded.

If you want to call a function that takes parameters, pass the parameter values
between the parentheses in the function call. The following example calls the
DisplayProjectedValue function, passing in three literal values as parameters:
DisplayProjectedValue(10000, 25, 6.0);

note
You don’t specify the parameter data types when you call a function. Just pro-
vide the parameter values.

The following example shows how to call a function that takes parameters and
returns a value. In this example, we call the GetInvestmentPeriod function to get
a value between 5 and 25. We assign the return value to a local int variable
named period:
int period = GetInvestmentPeriod(5, 25);

C04615675.p65 57 12/19/01, 10:32 AM


58 Microsoft Visual C++ .NET Step by Step

Calling Functions in the Sample Application


In this exercise, you will extend your sample application to include the function
calls you’ve just seen.
1 Open the Managed C++ Application project you created earlier in this
chapter.
2 Locate the main function. Just after the opening brace ({) of the main func-
tion, add the following statement. This calls the DisplayWelcome function:
DisplayWelcome();

3 Next, add the following statements to display an illustration of investment


growth. The DisplayProjectedValue function call will display the value of
10,000 after 25 years, at a growth rate of 6 percent:
Console::WriteLine(S"\nIllustration...");
DisplayProjectedValue(10000, 25, 6.0);

4 Next, add the following statements to ask the user how much they want to
invest and for how long. The GetInvestmentAmount and
GetInvestmentPeriod function calls return these values:
Console::WriteLine(
S"\nEnter details for your investment:");
double sum = GetInvestmentAmount();
int period = GetInvestmentPeriod(5, 25);

note
The GetInvestmentPeriod function has default values for each of its parameters
(the first parameter has a default value of 10, and the second parameter has a
default value of 25). You can use these default values when you call the func-
tion. For example, the following function call uses the default value for the
second parameter:
int period = GetInvestmentPeriod(5); // First parameter is5; second
parameter defaults to 25
If you use a default value for a parameter, you must use the default values for
each subsequent parameter in the parameter list. For example, the following
function call is invalid:
int period = GetInvestmentPeriod(, 20); // Try to use default value
for just the first parameter – illegal.

5 Finally, add the following statements to calculate and display the projected

C04615675.p65 58 12/19/01, 10:32 AM


Chapter 4 Using Functions 59

final value of this investment, assuming a growth rate of 6 percent:


Console::WriteLine(S"\nYour plan...");
DisplayProjectedValue(sum, period, 6.0);

6 Build your program, and fix any compiler errors.

Stepping Through the Application with the Debugger


In this exercise, you will step through the application with the debugger. This
will help you understand how the flow of control passes from one function to

4
another in your application.
This exercise will also illustrate the concept of variable scope. You will see how
local variables in a function come into scope during the function’s execution,

Using Functions
and disappear from scope at the end of the function.
1 Open the Managed C++ Application project from the previous exercise.
2 Locate the main function.
3 Insert a debug breakpoint by clicking in the gray border to the left of the
code. Click next to the DisplayWelcome function call, and you should see a
red dot appear in the border:

4 Start the debugging session by pressing F5. Once the program has loaded,
it will execute and stop at the breakpoint in the main function:

C04615675.p65 59 12/19/01, 10:32 AM


60 Microsoft Visual C++ .NET Step by Step

A yellow arrow appears in the margin, next to the DisplayWelcome func-


tion call. The yellow arrow indicates that this is the next statement to be ex-
ecuted.
5 Press F11 to step into the DisplayWelcome function. This debugger calls the
DisplayWelcome function, and displays a yellow arrow at the start of that
function:

6 Press F10 several times to step over each statement one at a time in the
DisplayWelcome function. This will cause a welcome message to be dis-
played in the Console window. At the end of the function, the debugger
will return you to the main function. The yellow arrow indicates the next
statement to execute in main:

C04615675.p65 60 12/19/01, 10:32 AM


Chapter 4 Using Functions 61

4
7 Press F10 to step over the Console::WriteLine function. The debugger ex-

Using Functions
ecutes the Console::WriteLine function, but doesn’t take you through it
step by step. The yellow arrow moves on to the DisplayProjectedValue
function call in main.
8 Press F11 to step into the DisplayProjectedValue function. From the Debug
menu, select Windows, then Locals. This displays the local variables in this
function:

The Locals window displays five local variables. The first three variables—
amount, years, and rate—are the function parameters. These variables are
already initialized with the values you passed into the function.
The last two variables—finalAmount and rateFraction—do not have mean-
ingful values. This is because the variables haven’t been assigned a value

C04615675.p65 61 12/19/01, 10:32 AM


62 Microsoft Visual C++ .NET Step by Step

yet. In fact, the debugger is misleading us a little here because the


finalAmount and rateFraction variables haven’t been declared yet. These
variables don’t really exist until the variable declaration statements further
on in the function.
9 Press F10 several times to step over the statements in the
DisplayProjectedValue function. Observe how the finalAmount and
rateFraction variables change during the function (the debugger displays
changed values in red, for prominence). Take a look at the Console window
to see what is displayed.
10 Keep pressing F10 until you reach the end of the DisplayProjectedValue
function, and return to main.
11 In main, press F10 to step over the Console::WriteLine statement.
12 Press F11 to step into the GetInvestmentAmount function. Step through the
statements in this function. When the debugger executes the ReadLine
statement, the Console window appears and you are asked to enter a num-
ber. Enter a number such as 20, and press Enter.
13 Keep stepping through the GetInvestmentAmount function until you return
to main.
14 Press F10 one more time, and then examine the local variables in main. No-
tice that the return value from GetInvestmentAmount has been assigned to
the sum local variable in main:

15 Continue stepping through the application in this manner until the applica-
tion terminates.

C04615675.p65 62 12/19/01, 10:32 AM


Chapter 4 Using Functions 63

tip
If the debugger takes you into a function that you are not interested in step-
ping through, press Shift+F11 to step out of the function. If you just want to
run the application without stopping at all, press F5.

Local and Global Scope

4
As you saw in the previous exercise, each function defines its own scope for lo-
cal variables. The local variables are created during function execution, and are
automatically destroyed at the end of the function. This means you can quite
happily have variables with the same name in different functions, without inter-

Using Functions
ference.
It is also possible to declare variables globally, outside of any function. Global
variables are visible in all function bodies that come after the global variable
definition in your source file. You can use global variables as a rudimentary way
of sharing information between multiple functions.

caution
Global variables are generally considered bad programming practice, especially
in object-oriented languages such as C++. Global variables have too much vis-
ibility: If a global variable gets corrupted, it’s difficult to pinpoint where the prob-
lem occurred. Global variables also introduce too much dependency between
functions.
For these reasons, you should use global variables sparingly. A better way of
sharing information between functions is to pass parameters and return values,
as you saw earlier in this chapter.

In this exercise, you will define a global variable in your application. You will
use this global variable in several functions to illustrate its global scope.
1 Open the Managed C++ Application project you created earlier in this
chapter.
2 Before the start of the main function, define a global integer variable
named numberOfYourFunctionsCalled, as follows:

C04615675.p65 63 12/19/01, 10:32 AM


64 Microsoft Visual C++ .NET Step by Step

3 Find the DisplayWelcome function in your code. At the start of this func-
tion, increment the numberOfYourFunctionsCalled variable as follows:

4 Add a similar statement to the start of every function in your application.


5 Modify the main function. At the end of this function, just before the return
statement, display the value of the numberOfYourFunctionsCalled variable:

6 Build and run your program. How many of your functions are called during
the program?

C04615675.p65 64 12/19/01, 10:32 AM


Chapter 4 Using Functions 65

Function Overloading
Visual C++ lets you provide many functions with the same name, as long as each
function has a different parameter list. This is known as function overloading.
Function overloading is useful if you have several different ways of performing a
particular operation, based on different input parameters.
For example, you might want to provide an average function to find the average
value of two double values, and another average function to find the average
value of an array of integers. You can define two functions to support these re-

4
quirements. Give each function the same name, average, to emphasize the com-
mon purpose of these functions. Define different parameter lists for the
functions, to differentiate one from another:
double average(double number1, double number2);

Using Functions
double average(int array[], int arraySize);

You must still implement both of these functions—there is no magic here! When
you call the average function, the compiler deduces which version of the func-
tion to call based on the parameter values you supply.

note
If you define overloaded functions, the functions must have a different param-
eter list. If you define overloaded functions that differ only in their return type,
you’ll get a compiler error.

In this exercise, you will define an overloaded version of the


DisplayProjectedValue function. The new version will calculate a random
growth rate between 0 and 20 percent, rather than use a specific growth rate.
1 Open the Managed C++ Application project you created earlier in this
chapter.
2 Add the following function prototype at the start of your code, near the
other function prototypes:
void DisplayProjectedValue(double amount, int years);

3 In the main function, locate the second call to the DisplayProjectedValue


function. Modify the function call so that you only pass two parameters into
the function:
DisplayProjectedValue(sum, period);

C04615675.p65 65 12/19/01, 10:32 AM


66 Microsoft Visual C++ .NET Step by Step

4 At the end of the program, define the new DisplayProjectedValue function


body as follows:
void DisplayProjectedValue(double amount, int years)
{
Random __gc * r = new Random();
int randomRate = r->Next(0, 20);
DisplayProjectedValue(amount, years, randomRate);
}

This function uses the Random class to calculate a random number between
0 and 20. The function passes the random number into the original version
of the DisplayProjectedValue function to calculate the value of the invest-
ment using this random rate.
5 Define breakpoints at the start of both of the DisplayProjectedValue func-
tions.
6 Build the program, and start it in the debugger.
7 Observe which versions of DisplayProjectedValue are called as your pro-
gram executes. See what random number the program uses for your
growth rate.
8 Run the program several times to verify that the growth rate really is ran-
dom.

Chapter 4 Quick Reference


To Do This

Declare a function Specify the return type of the function, followed by the
prototype function name, followed by the parameter list enclosed
in parentheses. Remember the semicolon at the end of
the function prototype. For example:
double MyFunction(int p1, short p2);
Define default Define default parameters in the function prototype, if
parameters required. Use an = operator, followed by the default
value. For example:
double MyFunction(int p1, short p2=100);
Define a function Specify the return type of the function, followed by the
body function name, followed by the parameter list enclosed
in parentheses. Do not specify default parameters here.
Define the function body within braces. For example:
double MyFunction(int p1, short p2)
{
int n = p1 + p2;

}

C04615675.p65 66 12/19/01, 10:32 AM


Chapter 4 Using Functions 67

Return a value Use the return keyword, followed by the value you
from a function want to return. For example:
return (p1 + p2) / 2.00;
Call a function Specify the function name, and pass parameter values
within parentheses. If the function returns a value, you
can assign it to a variable. For example:
double result = MyFunction(100, 175);
Define and use Define the global variable outside of any function. Use
global variables the variable in any subsequent function in the source

4
file. For example:
int myGlobal = 0;
void MyFunction()
{
myGlobal++;

Using Functions

}
Define and use Define several functions with the same name but
overloaded functions different parameter lists. Implement each function. Call
the version you want, using appropriate parameter
values. For example:
// Prototypes
void MyFunction(int p1);
void MyFunction(double p1, double p2);

// Function calls
MyFunction(100);
MyFunction(2.5, 7.5);

// Function bodies
void MyFunction(int p1)
{

}
void MyFunction(double p1, double p2)
{

}

C04615675.p65 67 12/19/01, 10:32 AM


C04615675.p65 68 12/19/01, 10:32 AM

You might also like