Microsoft Press - Visual C++.NET Step by Step PDF
Microsoft Press - Visual C++.NET Step by Step PDF
Getting Started
with C++
1
Hello, C++!
In this chapter, you’ll learn about
Hello, C++!
✔ C++ characteristics
✔ C++ functions
✔ C++ keywords and identifiers
✔ Creating a C++ program
int main()
{
cout << “Hello, World!” << endl;
return 0;
}
■ 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-
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.
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;
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.
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
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:
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.
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.
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.
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.
2 Click Add, and then click Add New Item to open the Add New Item dialog
box.
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.
Notice that the keywords automatically turn blue (providing you spell them
correctly).
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.
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.
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.
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
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.
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.
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.
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
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.
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
{
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
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>
2
int legs;
Introducing OOP
String* GetName() { return strName; };
private:
String *strName;
};
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;
}
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
3
Variables and
Operators
In this chapter, you’ll learn how to
✔ Declare (create) variables
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
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.
From these types built-in types, you can construct other types, as we'll see in this
and later chapters:
3
Or you can construct user-defined types by creating data structures and classes;
see the section on user-defined types below.
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];
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.
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.
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
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:
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.
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):
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”;
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
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
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.
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 '#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.
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.
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;
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
3
that combine the corresponding mathematical operation with the assignment
operation. For example:
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.
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.
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 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
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
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.
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
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.
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.
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.
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.
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
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.
{
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;
}
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)
{
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"Projected final value of investment: ");
Console::WriteLine(finalAmount);
return;
}
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? ");
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.
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.
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.
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);
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
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:
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:
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
15 Continue stepping through the application in this manner until the applica-
tion terminates.
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.
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:
3 Find the DisplayWelcome function in your code. At the start of this func-
tion, increment the numberOfYourFunctionsCalled variable as follows:
6 Build and run your program. How many of your functions are called during
the program?
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.
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.
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;
…
}
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)
{
…
}