Teach Yourself Visual C++® 5 in 24 Hours

Previous chapterNext chapterContents


- Hour 3 -
Structures, Classes, and the MFC Class Library

In the first two hours, you have learned some of the basic concepts behind C++, and you have written some simple programs. In this hour, you will be introduced to some more advanced Visual C++ programming topics. In particular, you will learn

You will also build sample programs that illustrate the topics you learn about in this hour.

Using Functions

New Term: A function is a group of computer instructions that performs a well-defined task inside a computer program.

Functions are one of the primary building blocks of C and C++ applications. Functions provide a way to break up a large program into more manageable parts. At the same time, functions make it possible to perform the same task at various points within the program without repeating the code.

For example, If you buy a wagon, you'll find that it comes with a full set of assembly instructions and has four identical wheels. Why should the instructions repeat the steps to assemble a wheel four times? It is much easier to describe the wheel assembly process once and indicate that you perform the process for each wheel. The wheel assembly instructions are a module (function), within the full set of assembly instructions (program), that is executed four times.

Every C++ program has at least one function; this function is called main. The main function is called by the operating system when your application starts; when main has finished executing, your program has finished.

Declaring Function Prototypes

Before you can use a function, you must declare it by supplying a function prototype to the compiler. To declare a function, you specify the function's name, its return value, and a list of any parameters that are passed to it, as shown here:

int CalculateAge(int nYearBorn);

This line is a function prototype for the CalculateAge function, which takes a single integer as a parameter and returns an integer as its result. A function that returns no value is declared as returning the void type.

New Term: The traditional way to provide function prototypes is to place them in header files, which are usually named with an .h extension.

Header files that are part of the C++ standard library do not use the .h extension; two examples of standard header files are iostream and math. These header files contain all the prototypes and other declarations needed for IO streams and math functions to be compiled correctly.

Defining Functions

A function is defined the same way the main function is defined. All function definitions follow the same pattern; it's basically the function prototype with the function's body added to it. The function definition always consists of the following:

Listing 3.1 shows how to use a function to display the Hello World! message. To run this project, create a new console-mode project named HelloFunc, using the steps described for the Hello and Hello2 projects in the first two hours.

TYPE: Listing 3.1. The Hello World! program rewritten to use a function.

#include <iostream>
using namespace std;
// Function prototype
void DisplayAge(int nAge);

int main()
{
    DisplayAge(42);
    return 0;
}

void DisplayAge(int nAge)
{
    cout << "Hello World! I'm " << nAge << " years old."  endl;
}

Because the function doesn't return a value to the calling function, the return type is defined as void.

Calling Functions

In the C++ language, the act of transferring control to a function is known as calling the function. When a function is called, you supply a function name and a list of parameters, if any. The following steps take place when a function is called:

1. The compiler makes a note of the location from which the function was called and makes a copy of the parameter list, if any.

2. Any storage required for the function to execute is temporarily created.

3. The called function starts executing, using copies of the data that was supplied in the parameter list.

4. After the function has finished executing, control is returned to the calling function, and memory used by the function is released.

These steps are shown in Figure 3.1, which uses the function from Listing 3.1 as an example.

Figure 3.1.
Steps involved in calling a function.


Just a Minute: The requirement that you declare functions before using them is an extension of the C++ type system. Because function prototypes are required, the compiler can detect errors such as incorrect parameters used in a function call.

What Are Structures?

New Term: A structure is a data type that is an aggregate; that is, it contains other data types, which are grouped together into a single user-defined type.


Just a Minute: Structures are commonly used when it makes sense to associate two or more data variables.

An example of a structure is a payroll record, where the number of hours worked and the pay rate are combined in a structure, as shown in Figure 3.2.

Figure 3.2.
Structures are made up of member variables.

Declaring a structure introduces a new type of variable into your program. Variables of this new type can be defined just like int, char, or float variables are defined. Listing 3.2 is an example of how a structure is typically used.

TYPE: Listing 3.2. Using a structure to calculate a weekly salary.

#include <iostream.h>

struct  TIME_REC
{
    double   dHours;
    double   dRate;
};

int main()
{
    TIME_REC    payrollRecord;

    payrollRecord.dHours = 40.0;
    payrollRecord.dRate = 3.75;

    cout << "This week's payroll information:" << endl;
    cout << "Hours worked : " << payrollRecord.dHours << endl;
    cout << "Rate         :$" << payrollRecord.dRate  << endl;

    double dSalary = payrollRecord.dRate * payrollRecord.dHours;
    cout << "Salary       :$" << dSalary  << endl;

    return 0;
}

What Are Classes?

New Term: A class allows data and functions to be bundled together and used as if they are a single element. Classes typically model real-world concepts that have both data and some sort of behavior, although this is not a hard and fast rule.

Classes are similar to structures; in fact, classes really are just structures with a different name. Classes have one feature that makes them very useful for object-oriented programming: Unless a member of a class is specifically declared as public, that member is generally not accessible from outside the class. This means that you can hide the implementation of methods behind the external interface.


Just a Minute: Like functions, classes are an important part of the C++ programming language. In fact, one of the earliest names for C++ was C with Classes.

New Term: An instance of a class, sometimes called an object, is an occurrence of a class. An instance of one of your classes can be used or manipulated inside your programs.

You normally use classes to model objects in your program. Member functions, described in the next section, are used to control the state of an object, as well as to access any data contained in it.

In programs written with MFC, classes are used to model different parts of the application, such as the window frame, menus, buttons, and other controls. Member functions are used to handle specific work that needs to be handled by the class.

Classes Versus Instances

Classes and instances of classes are not the same things--this can sometimes be a confusing concept if you are new to C++ or object-oriented programming. Think of a class as the description of an object; an instance of a class is a concrete occurrence of that class.

Constructors

New Term: A constructor, sometimes called a "ctor," is a special member function that is created when an object of the class is created.

A constructor always has the same name as the class and never has a return value, not even void. The purpose of the constructor is to place a newly created object into a known state. Typically, constructors can allocate system resources, clear or set variables, or perform some other type of initialization.

Destructors

New Term: A destructor, sometimes called a "dtor," is a special member function that is called as an object is destroyed. The destructor is declared as having no return type and is never declared with a parameter list. The name of the destructor is the class name prefixed by a tilde (~) character.

It is not necessary to define a destructor unless there are specific tasks that must be performed to clean up after an object, such as releasing system resources that might have been allocated.

Using MFC for Windows Programming

In the first hour, you created an MFC program using AppWizard. When you use AppWizard to create a project, it might seem that you get a great deal of functionality for free. However, a great deal of code is generated--even a simple program like HelloMFC results in a large number of source files.

MFC doesn't need to be that complicated. In fact, you can write a very simple MFC program that fits in a single source file and is about one page long.

The HelloWin MFC Example

Listing 3.3 is an example of a simple MFC program that displays a Hello World message in the center of the client window, much like the HelloMFC program you created in the first hour.

TYPE: Listing 3.3. A simple Windows program written using C++ and MFC.

#include <afxwin.h>

// The CHelloApp class
class CHelloApp : public CWinApp
{
    public:
        BOOL InitInstance();
};

// The CHelloWnd class
class CHelloWnd : public CFrameWnd
{
    public:
        CHelloWnd();
    protected:
        afx_msg void OnPaint();
        DECLARE_MESSAGE_MAP()
};

// InitInstance - Returns TRUE if initialization is successful.
BOOL CHelloApp::InitInstance()
{
    m_pMainWnd = new CHelloWnd;
    if( m_pMainWnd != 0 )
    {
        m_pMainWnd->ShowWindow( m_nCmdShow );
        m_pMainWnd->UpdateWindow();
        return TRUE;
    }
    else
        return FALSE;
}

// Create a message map that handles one message - WM_PAINT
BEGIN_MESSAGE_MAP( CHelloWnd, CFrameWnd )
    ON_WM_PAINT()
END_MESSAGE_MAP()

CHelloWnd::CHelloWnd()
{
    Create( NULL, "Hello" );
}

// OnPaint - Handles the WM_PAINT message from Windows.
void CHelloWnd::OnPaint()
{
    CPaintDC    dc(this);
    dc.TextOut(50, 50, "Hello World!", 12);
}

// Create a single instance of the application.
CHelloApp   theApplication; 

The simple Windows program provided in Listing 3.3 might seem large, but it's actually about half the size of a similar program written in C. Using the MFC class library enables you to use a large amount of source code that has already been written for you. There is a lot of strange-looking code in Listing 3.3, so don't try to understand it all right now.

Building the HelloWin Example

To build the program, create an MFC Windows project named HelloWin. Begin by selecting File | New from the Visual C++ main menu; select the Projects tab in the New dialog box. Next, select Win32 Application as the project type. You must also specify a name and location for your project, just as you did for the projects in the first two hours.

After the project has been created, open a new C++ source file document and enter the contents of Listing 3.3 exactly as they are shown. Save the file as HelloWin.cpp and add it to the project. (If necessary, refer to Hour 1, "Introducing Visual C++ 5," for specific instructions.)

Set the linking options for the project by selecting Project | Settings from the main menu. On the tab marked General is an item labeled Microsoft Foundation Classes. It will have the value Not Using MFC. Change the selection to Use MFC in a Shared Dll. You can do this by clicking on the down arrow beside the Not Using MFC selection. This opens a box where you can then make the appropriate selection.

Compile the HelloWin project by selecting Build | Build HelloWin.exe from the main menu (or Press F7).

To start the HelloWin program, select Build | Start Debug | Go from the main menu (or Press F5). Figure 3.3 shows an example of HelloWin running.

Figure 3.3.
The HelloWin program displaying its message in a window.

The Common Elements of a Windows Program

Two elements are found in almost every Windows program; each of these elements can be found in the HelloWin program that you just compiled and ran:

Windows Are Everywhere

One of the fundamental concepts in Windows programming is that everything you see is a window. Some examples of windows are

All windows have a common set of operations that can be applied to them. They are all re-sized, moved, enabled, disabled, hidden, and displayed in the same way.

The Client and Non-Client Areas

A window is divided into two main areas, as shown in Figure 3.4:

Figure 3.4.
Client and non-client areas of a window.

The non-client area of a window is normally maintained by Windows; your applications will normally be concerned only with the client area.

Messages and Functions

When Windows needs to communicate with an application, it sends it a message. A message is similar to a function call--in fact, the MFC library will route most messages as function calls into your application. For example, in an AppWizard application, the MFC library calls the OnDraw function whenever Windows sends a WM_PAINT message.

When your application communicates with a window, it will usually send it a message. To enable or disable a control, you must send the control a WM_ENABLE message. When using C, this process is very tedious and error prone. MFC simplifies things by providing functions that you can call and then handling the message sending for you.

What Are Statements and Expressions?

Statements and expressions are the elements defined by the C++ language that are converted into machine code by the compiler to build your C++ programs. Seems like a textbook-type definition, doesn't it? In reality, though, it is very hard to define exactly what they are. When talking about a building, we can say that it is made of bricks, boards, and other things; we can define the brick or board very easily. In the case of the C++ programming language, it is much more difficult. Here we are dealing with abstract concepts. The difference between a statement and expression is very subtle, as you will soon see. Although it appears to be confusing at first, the language will become understandable with practice. Eventually the C++ language will become as natural to you as your native language.

Just like the simple Hello programs, all C++ programs are made up of statements and expressions. Expressions and statements range from the simple statements that were shown in the Hello programs to very complex expressions that stretch across several lines.

Statements

All statements end with semicolons. In fact, the simplest statement is called the null statement, and it consists of only a single semicolon, as follows:

;

The null statement isn't used often; it's used only in situations in which the C++ syntax requires a statement, but no real work needs to be done.

You use a statement to tell the compiler to perform some type of specific action. For example, you know from the console mode programs you created that the following statement will cause the characters Hello World! to be displayed on your screen:

cout << "Hello World!" << endl;

Declarations

A declaration is another type of statement. As discussed earlier, declarations introduce a variable to the compiler. The following line is an example of a simple declaration:

int myAge;

This tells the compiler that myAge is an integer.

Assignment

An assignment expression is used to assign a value to a variable, using the assignment operator, =, as follows:

int     myAge;
myAge = 135;

Every expression has a value. The value of an assignment expression is the value of the assignment. This means that the following statement assigns the value 42 to the variables yourAge and myAge:

myAge = yourAge = 42;

The program in Listing 3.4 demonstrates how to assign a value to a variable.

TYPE: Listing 3.4. A C++ program that assigns a value to a variable.

#include <iostream>
using namespace std;
int main()
{
    int myAge;

    myAge = 42;
    cout << "Hello" << endl;
    cout << "My age is " << myAge << endl;

    return 0;
}

The assignment operator is just one example of the operators available in C++. More operators are discussed in the next section.

Other Common Expressions and Operators

The C++ language contains operators that you can use to write addition, subtraction, multiplication, and other expressions. Some common math operators are shown in Table 3.1.

Table 3.1. Some common math operators used in C++.

Operator Description
+ Addition
- Subtraction
/ Division
* Multiplication

All math operators group from left to right. The multiplication and division operators have a higher precedence than the addition and subtraction operators. This means that the following expressions are equivalent: a + 5 * 3 a + 15 You can use parentheses to force an expression to be evaluated in a preferred order. Note the grouping of the following expression: (a + 5) * 3 This expression adds 5 to the value stored in a and then multiplies that value by 3. The math operators can also be combined with an assignment operator, as follows:

int myAge;
    myAge = 40 + 2;

The expression 40 + 2 has a value of 42. After that value is calculated, the value of the expression is stored in the myAge variable.

Rectangles and Regions

The rectangle is a fundamental component of most Windows programs. Because most windows and controls are rectangular, it isn't surprising that one of the most commonly used data structures in Windows programming is used to represent a rectangle.

Rectangles are often used to represent the position or size of all types of windows: main windows as well as controls, toolbars and dialog boxes. There are two basic types of rectangle coordinates:

Screen rectangle coordinates are often used when moving a window in relation to the entire screen. Client rectangles are most commonly used when positioning controls or drawing inside a control or other window.

When requesting the dimensions of a rectangle, you must pass a CRect variable to one of the Windows rectangle functions. The following two lines of code declare an instance of CRect as a variable and pass it to the GetClientRect function:

CRect rcClient;
GetClientRect(rcClient);

The next example uses a client area rectangle to display a message to the user, just like the HelloMFC program in the first hour. The new example will draw the message in the center of the client area; if the window is resized, the message will be redrawn in the center of the new rectangle.

Create an MFC AppWizard application named HelloRect, following the steps presented in the first hour. Modify the OnDraw function found in the CHelloRectView class so that it looks like the function shown in Listing 3.5.

TYPE: Listing 3.5. Using a rectangle to center a message in a window.

void CHelloRectView::OnDraw(CDC* pDC)
{
    CRect       rcClient;
    GetClientRect(rcClient);
    pDC->DrawText("Hello Client Rectangle!", -1, rcClient,
                 DT_SINGLELINE | DT_CENTER | DT_VCENTER );
}

Build the HelloRect application, and run it from Developer Studio. Note that if you resize the window, the message is redrawn so that it remains in the center of the client area.

Summary

In this hour, you have learned about some of the more advanced building blocks that make up C++ programs: functions, structures, and classes. You also looked at some basic information about the MFC class library and built an MFC application without using ClassWizard.

Q&A

Q What is the difference between a rectangle that uses screen coordinates and a rectangle that uses client coordinates?

A Every window in a Windows application can be represented by a rectangle; this rectangle will typically use either screen or client coordinates. The rectangle that results from these coordinates is always the same, the difference is only in the point of reference that is used to measure the rectangle.

Q Can a structure have member functions?

A Absolutely. A class and a structure are exactly the same, except that all members of a structure are accessible by default, while class members are private (not accessible) by default. You will learn more about access restrictions in the next hour.

Q Why is no function prototype required for main()?

A The short answer: because the C++ standard says you don't need one. The purpose of function prototypes is to introduce new functions to the compiler; because every C++ program is required to have a main function, no function is necessary.

Workshop

The Workshop is designed to help you anticipate possible questions, review what you've learned, and begin thinking ahead to putting your knowledge into practice. The answers to the quiz are in Appendix B, "Quiz Answers."

Quiz

1. What are some examples of the different types of windows found in a Windows application?

2. What is a function?

3. What are the four parts of a function definition?

4. How are classes different from structures?

5. What function is called when an instance of a class is created?

6. What function is called when an instance of a class is destroyed?

7. What is the difference between the client and non-client areas?

8. What is the value of the expression a = 42?

9. What symbol is used for multiplication?

10. What symbol is used for division?

Exercises

1. Write a console-mode program that asks for a distance in miles and converts the distance into feet. There are 5,280 feet in a mile.

2. Modify the HelloWin program to display different messages in different parts of the main window.


Previous chapterNext chapterContents


Macmillan Computer Publishing USA

© Copyright, Macmillan Computer Publishing. All rights reserved.