ÄúµÄλÖãºÑ°ÃÎÍøÊ×Ò³£¾±à³ÌÀÖÔ°£¾C/C++±à³Ì£¾Teach Yourself Visual C++ 6 in 21 Days


Teach Yourself Visual C++ 6 in 21 Days

Previous chapterNext chapterContents


- 16 -
Creating Your Own Classes and Modules



Sometimes you need to build a set of application functionality that will be used in an application that another programmer is working on. Maybe the functionality will be used in a number of applications. Another possibility is that you want to separate some functionality from the rest of the application for organizational purposes. You might develop this separate set of functionality and then give a copy of the code to your friend to include in his application, but then every time you make any changes to your set of functionality, it has to be reincorporated into the other set of application code. It would be much more practical if you could give a compiled version of your functionality to the other programmer so that every time you updated your part, all you had to hand over was a new compiled file. The new file could just replace the previous version, without having to make any changes to the other programmer's code.

Well, it is possible to place your set of functionality into a self-contained compiled file, link it into another programmer's application, and avoid adding any new files to the finished application. Today, you will learn

  • How to design your own classes.

  • How to create compiled modules that can be linked into other applications.

  • How to include these modules into an application.

Designing Classes

You've already designed and built your own classes over the past few days, so the basics of creating a new class is not a new topic. Why did you create these classes? Each of the new classes that you created encapsulated a set of functionality that acted as a self-contained unit. These units consisted of both data and functionality that worked together to define the object.

Encapsulation

Object-oriented software design is the practice of designing software in the same way that everything else in the world is designed. For instance, you can consider your car built from a collection of objects: the engine, the body, the suspension, and so on. Each of these objects consists of many other objects. For instance, the engine contains either the carburetor or the fuel injectors, the combustion chamber and pistons, the starter, the alternator, the drive chain, and so on. Once again, each of these objects consists of even more objects.

Each of these objects has a function that it performs. Each of these objects knows how to perform its own functions with little, if any, knowledge of how the other objects perform their functions. Each of the objects knows how it interacts with the other objects and how they are connected to the other objects, but that's about all they know about the other objects. How each of these objects work internally is hidden from the other objects. The brakes on your car don't know anything about how the transmission works, but if you've got an automatic transmission, the brakes do know how to tell the transmission that they are being applied, and the transmission decides how to react to this information.

You need to approach designing new classes for your applications in the same way. The rest of the application objects do not need to know how your objects work; they only need to know how to interact with your objects. This principle, called encapsulation, is one of the basic principles of object-oriented software.

Inheritance

Another key principle of object-oriented software design is the concept of inheritance. An object can be inherited from another object. The descendent object inherits all the existing functionality of the base object. This allows you to define the descendent object in terms of how it's different from the base object.

Let's look at how this could work with a thermostat. Suppose you had a basic thermostat that you could use in just about any setting. You could set the temperature for it to maintain, and it would turn on the heating or the air-conditioning as needed to maintain that temperature. Now let's say you needed to create a thermostat for use in a freezer. You could start from scratch and build a customized thermostat, or you could take your existing thermostat and specify how the freezer version differs from the original. These differences might include that it's limited to turning on the air conditioning and could never turn on the heater. You would probably also put a strict limit on the range of temperatures to which the thermostat could be set, such as around and below 32[infinity] Fahrenheit, or 0[infinity] Celsius. Likewise, if you needed a thermostat for an office building, you would probably want to limit the temperature range to what is normally comfortable for people and not allow the temperature to be set to an extremely cold or hot setting.

With inheritance in creating your own classes, this method just described represents the same principle that you want to apply. If possible, you should start with an existing C++ class that has the basic functionality that you need and then program how your class is different from the base class that you inherited from. You have the ability to add new data elements, extend existing functionality, or override existing functionality, as you see fit.

Visual C++ Class Types

In most application projects, when you are creating a new class, you have a few options on the type of class that you are creating. These options are

  • Generic class

  • MFC class

  • Form class

Which of these types of classes you choose to create depends on your needs and what your class will be doing. It also depends on whether your class needs to descend from any of the MFC classes.

Generic Class

You use a generic class for creating a class that is inherited from a class you have already created. This class type is intended for creating classes that are not inherited from any MFC classes (although you have already seen where you need to use it to create classes that are based on MFC classes). If you want to create a more specialized version of the CLine class, for instance, a CRedLine class, that only drew in red, you create it as a generic class because it's inherited from another class that you created.

When you create a generic class, the New Class Wizard tries to locate the declaration of the base class (the header file with the class declared). If it cannot find the appropriate header file, it tells you that you might need to make sure that the header file with the base class definition is included in the project. If the base class happens to be an MFC class that is not accessible as an MFC class (such as CObject), then you can ignore this warning because the correct header file is already part of the project.

MFC Class

If you want to make a reusable class that is based on an existing MFC class, such as an edit box that automatically formats numbers as currency, you want to create an MFC class. The MFC class type is for creating new classes that are inherited from existing MFC classes.

Form Class

The form class is a specialized type of MFC class. You need to create this type of class if you are creating a new form style window. It can be a dialog, form view, or database view class. This new class will be associated with a document class for use with the view class. If you are building a database application, you will probably create a number of this style of classes.

Creating Library Modules

When you create new classes for your application, they might be usable in other applications as well. Often, with a little thought and effort, classes you create can be made flexible enough so that they could be used in other applications. When this is the case, you need some way of packaging the classes for other applications without having to hand over all your source code. This is the issue that library modules address. They allow you to compile your classes and modules into a compiled object code library that can be linked into any other Visual C++ application.

Library modules were one of the first means available to provide compiled code to other programmers for use in their applications. The code is combined with the rest of the application code by the linker as the final step in the compilation process. Library modules are still a viable means of sharing modules with other developers. All the developer needs is the library (.lib) file and the appropriate header files that show all the exposed classes, methods, functions, and variables, which the other programmer can access and use. The easiest way to do this is to provide the same header file that you used to create the library file, but you can also edit the header so that only the parts that other programmers need are included.

By using library files to share your modules with other programmers, you are arranging that your part of the application is included in the same executable file as the rest of the application. Your modules are not included in a separate file, such as a DLL or ActiveX control. This results in one less file to be distributed with the application. It also means that if you make any changes to the module, fix any bugs, or enhance any functionality, then the applications that use your module must be relinked. Using library files has a slight disadvantage to creating DLLs, where you may be able to just distribute the new DLL without having to make any changes to the application, but you'll learn all about that tomorrow.

Using Library Modules

To get a good idea of how to use library modules, it's helpful to create a library module, use it in another application, and then make some modifications to the library module. For today's sample application, you'll create a module that generates a random drawing on the window space specified. It'll be able to save and restore any of these drawings. You'll then use this module in an SDI application, where every time a new document is specified, a new drawing is generated. The initial module will only use eight colors and will generate only a limited number of line sequences. Later, you'll modify the module so that it will generate any number of colors and will generate a larger number of line sequences.

Creating the Library Module

To create a library module project, you need to specify in the New dialog that you want to create a Win32 Static Library, as shown in Figure 16.1. This tells Visual C++ that the output from the project compilation will be a library module instead of an executable application. From there, all you have to do is define the classes and add the code. You have the options of including support for MFC and using precompiled headers in your project, as in Figure 16.2, the only step in the Project Wizard.

The library that you will create for today's sample application will consist of two classes. The first class will be the CLine class that you first created on Day 10, "Creating Single Document Interface Applications." The second class will be the class that creates the random drawings on the drawing surface. This class will contain an object array of the CLine objects that it will create and populate with each of the drawing efforts. This second class will also need functionality to save and restore the drawing, as well as to delete the existing drawing so that a new drawing can be started. It will need to know the dimensions of the drawing area so that it can generate a drawing that will fit in the drawing area. Once you create this module, you'll take a look at how you can use this module in an application project.

FIGURE 16.1. Specifying a library module project.

FIGURE 16.2. Specifying project support options.

Creating a Library Project

To start the library project for today's example, you need to create a new project, specifying that the project is a Win32 Static Library project. Give the project a suitable name and click OK to create the project.

For today's sample project, specify on the one wizard step to include both MFC and precompiled header support. Although the precompiled header support is not necessary, it will speed up most compiles that you perform while building the module.

Once you create your module project, you'll find yourself working with a project that has no classes. You've got a blank slate from which you can create


Previous chapterNext chapterContents