Microsoft Visual C++ .NET 2003 Kick Start

The simplest way to write a class library to be called from an application is to make a second project within the solution that already contains the application. A library like this is designed to be used by a single application. It's quite simple to write other applications that can also use it.

Writing a class library should always start with design. In order to keep the code simple and concentrate on the connections between the calling application and the class library, the design in this sample library is simple. The library does arithmetic. There is a class called Arithmetic , with methods such as Add() , Subtract() , Multiply() , and Divide() . These methods each take two double parameters and return double results.

Future versions of this library might add more classes to it, such as a class that represents complex numbers , or matrices, or fractions represented as a numerator and a denominator instead of as a floating-point number. A class library with only one class in it can serve as a useful illustration, even if it's not really a very useful library.

The user interface for the sample class library in this chapter could be a Windows application or a console application. Just for simplicity, this chapter builds a console application to demonstrate how to use a class library.

To create the sample application, follow these steps:

  1. In Visual Studio, choose File, New, Blank solution and name the solution AllInOne .

  2. In Solution Explorer, right-click the solution and choose Add, New Project.

  3. Select a C++ Win32 project and name it Math Library . On the Win32 Application wizard, change the Application Settings to a static library. Accept all the other defaults.

  4. In Solution Explorer, right-click the solution and choose Add, New Project.

  5. Select a C++ Win32 Console application and name it Harness . Accept all the defaults on the wizard.

  6. Right-click the MathLibrary project in Solution Explorer and choose Add, Add Class. Select Generic C++ Class and click Open.

  7. On the Generic C++ Class wizard, fill in Arithmetic for the class name. The other boxes are filled in for you. Click Finish.

At this point you have two projects in a solution, and the MathLibrary project has a header file, Arithmetic.h and an implementation file, Arithmetic.cpp. Listing 5.1 shows the simple definition of this class, and Listing 5.2 shows the implementation. The constructor and destructor were generated by the wizard.

Listing 5.1 Arithmetic.hClass Definition

#pragma once class Arithmetic { public: Arithmetic(void); ~Arithmetic(void); double Add(double num1, double num2); double Subtract(double num1, double num2); double Multiply(double num1, double num2); double Divide(double num1, double num2); };

Listing 5.2 Arithmetic.cppClass Implementation

#include "StdAfx.h" #include ".\arithmetic.h" Arithmetic::Arithmetic(void) { } Arithmetic::~Arithmetic(void) { } double Arithmetic::Add(double num1, double num2) { return num1 + num2; } double Arithmetic:: Subtract(double num1, double num2) { return num1 - num2; } double Arithmetic::Multiply(double num1, double num2) { return num1 * num2; } double Arithmetic::Divide(double num1, double num2) { return num1 / num2; }

The code for the test harness calls these member functions. To write code that calls these functions, you need to ensure that the compiler knows where to find the definition of the class and the linker knows where to find the compiled code for the implementation.

The harness file must include the header file for the Arithmetic class. You might simply add this line:

#include "arithmetic.h"

This won't work: arithmetic.h and harness.cpp are in different folders. Each is in a project folder beneath the solution folder. You could provide the full path to the header file:

#include "../MathLibrary/arithmetic.h"

This will work, but it's not very maintainableif you ever rearrange the folders, you might have to change hundreds of include statements throughout a large project. It's better to arrange with Visual Studio to look in the MathLibrary folder whenever it's looking for header files that you've included. Here's how:

  1. In Solution Explorer, right-click the Harness project and choose Properties.

  2. Under Configuration Properties on the left, expand the C/C++ folder. Click General. Click next to Additional Include Directories on the left (see Figure 5.1) and type the relative path to the MathLibrary folder:

    ../MathLibrary

    Figure 5.1. Adding another directory to those that are searched for include (.H) files.

  3. Click OK. Now the compiler knows how to find the arithmetic.h file.

  4. In Solution Explorer, right-click the Harness project and choose Properties.

  5. Under Configuration Properties on the left, expand the Linker folder. Click Input. Click next to Additional Dependencies on the left (see Figure 5.2) and type the relative path to the Debug build of the MathLibrary folder:

    ../MathLibrary/Debug/MathLibrary.lib

    Figure 5.2. Adding another library to those that are linked together to form your executable file.

  6. Click OK. Now the linker will be able to find MathLibrary.lib, which holds the compiled code for the methods of the Arithmetic class.

All that remains is to write some test code that exercises a few of the Arithmetic member functions. That looks like this:

#include "stdafx.h" #include "arithmetic.h" #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { Arithmetic a; cout << "1.2 + 3.2 = " << a.Add(1.2, 3.2) << endl; cout << "2.1 * 3 = "<< a.Multiply(2.1, 3) << endl; cin.get(); return 0; }

Build the entire solution (choose Build, Build Solution) and you're almost ready to test. When a solution holds more than one project, one is the startup project, the one that runs when you press F5. The name of that project is bold in Solution Explorer. By default, the project you create first ( MathLibrary in this case) is the startup project. Right-click the Harness project in Solution Explorer and choose Set As Startup Project. Now run the test harness by pressing F5. You should see something like this:

1.2 + 3.2 = 4.4 2.1 * 3 = 6.3

There you have ita simple class library in one project, and a simple test harness in another. In reality, your class library can be as complex as you like. You can define as many classes as you like. If your overall architecture has several layers, don't try to put more than one layer into each .LIB file. You'll have more flexibility if each layer can be reused independently. And think twice about splitting a layer across two .LIB files. If they can really be used independently, perhaps they represent two layers . And if they can't be used independently, why set other developers up for trouble by implying that they can be? It's better to keep logical units, such as a layer or module, intact.

Because your library was statically linked (from a .LIB file) into your application, when you distribute the application, you only need to distribute the .EXE file. All the code from the library that your application uses has been copied into the .EXE file. This can make .EXE files large, which is one of the appeals of DLL programming, but it makes distribution simplethere is only one file to distribute. You can test this by copying Harness.exe to any other folder on your hard drive, and then double-clicking it to run it. It will run perfectly .

Категории