Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ Timesaving Techniques (2005) [eng].pdf
Скачиваний:
65
Добавлен:
16.08.2013
Размер:
8.35 Mб
Скачать

38 Working with Arrays of Object

Technique Pointers

Save Time By

Understanding arrays of object pointers

Implementing arrays of object pointers

Interpreting output

Although simple arrays of objects are easy to work with, arrays of pointers that indicate objects are slightly more complicated to handle. The syntax for creating and deleting these arrays is a little

more difficult; heterogeneous arrays of pointers that point to a common base object require a bit more work — and this technique guides you through what must be done. C++ allows you to store pointers to all related classes — that is, those derived from a common base — in a single array, while keeping track of their types and sizes. This can save you a lot of time, by allowing you to place all of the related objects in a single array while processing them differently using their derived types.

You can save a lot of time by storing all objects that derive from a common base in a single array for access — as long as you have a way to access the objects consistently. If you do so, you must use a virtual destructor in the base class to insure that all de-allocations are done properly. If you do not do this, the destructors for the derived classes will not be called, and potential memory leaks can occur.

Creating an Array of Heterogeneous Objects

If you are working with a batch of different classes, all derived from a single base class, it can be advantageous to store them all in one place. For one thing, you only have one array to work with. For another, because the objects are all related, it is likely that you will be doing the same processing on them all at the same time. Let’s look at an example of creating a heterogeneous array that stores multiple classes of objects.

1. In the code editor of your choice, create a new file to hold the code for the implementation of the source file.

In this example, the file is named ch38.cpp, although you can use whatever you choose.

2. Type the code from Listing 38-1 into your file.

Better yet, copy the code from the source file on this book’s companion Web site.

214 Technique 38: Working with Arrays of Object Pointers

LISTING 38-1: CREATING AN ARRAY OF OBJECT POINTERS

#include <stdio.h> #include <string.h>

class Base

{

char *ptr; public:

Base(void)

{

ptr = NULL;

}

Base( const char *str )

{

setString( str );

}

virtual ~Base()

{

printf(“Base::~Base called\n”); delete ptr;

}

void setString( const char *str )

{

ptr = new char[strlen(str)+1]; strcpy( ptr, str );

}

const char *getString()

{

return ptr;

}

};

class Derived : public Base

{

private: int _num;

public:

Derived(void)

: Base(“DerivedVoid”)

{

_num = 0;

}

Derived( int nVal )

: Base(“DerivedFull”)

{

_num = nVal;

}

virtual ~Derived()

{

printf(“Derived::~Derived called\n”);

}

void setVal( int nVal )

{

_num = nVal;

}

int getVal ( void )

{

return _num;

}

};

const int NumElements = 3;

int main(void)

 

 

{

 

1

Base **bArray = new Base*[10];

for ( int i=0;

i<NumElements; ++i )

2

bArray[i] =

new Derived(i);

// Print them out

 

for ( int j=0;

j<NumElements; ++j )

 

printf(“Object %s - %d\n”, bArray[j]- >getString(), ((Derived *)bArray[j])- >getVal());

// Delete them

for ( int i=0; i<NumElements; ++i ) delete bArray[i];

delete [] bArray; return 0;

}

The above code listing illustrates how we create an array of pointers and store data in that array. As you can see at 1, allocating an array of pointers is no different than allocating any other sort of array in C++. The difference here is that while the array space is allocated, no actual objects are created. This is because we are allocating space for pointers to the objects, not objects themselves. The actual allocation of objects and the space they consume is illustrated at the line marked 2. Note that even though we have an array of Base pointers, we can create and store Derived pointers in the array, since they are a derived form of Base.

Creating an Array of Heterogeneous Objects

215

3. Save the source file in your code editor and close the code editor.

4. Compile the source code with the compiler of your choice on the operating system of your choice.

When the program is run, if you have done everything properly, you should see the following output in the shell window:

$ ./a.exe

Object DerivedFull - 0 Object DerivedFull - 1 Object DerivedFull - 2 Derived::~Derived called Base::~Base called Derived::~Derived called Base::~Base called Derived::~Derived called Base::~Base called

The output here illustrates that the array of pointers is created as we expected. The string stored in the Base class was created from the Derived constructor, which is what we anticipated. The destruction of the objects does chain upward to call both the Base class and Derived class destructors. In short, this code works exactly as advertised.

The ability to work with an array of heterogeneous pointers is quite powerful in C++, because it means that you need not know what sort of object you are working with. Had we created virtual methods for getting and setting the values in the Base class, we would not even have to cast the object in the printf in the main function.

39 Implementing a

Spreadsheet

Technique

Save Time By

Creating a simple spreadsheet implementation

Creating the Column class

Creating the Row class

Creating the

Spreadsheet class

Testing your spreadsheet

One of the most famous (or perhaps infamous) applications to help make the personal computer popular was the spreadsheet — nothing more than a grid of cells arranged in rows and columns —

in other words, a two-dimensional array. Spreadsheets have more functionality than simple arrays (for example, you can build in formulae), but at its heart, a spreadsheet is an array of rows and columns. This technique uses the Standard Template Library (STL) to set up and implement a spreadsheet shell. The result can easily be used to create a real spreadsheet implementation. Spreadsheets are common elements of applications these days, from doing presentations of data to what-if analysis. By having a generic spreadsheet class that you can drop into your next project, you will find that you save a lot of time in both the design and implementation phase of the project.

The implementation shown here isn’t designed to work with or interpret formulae, but it will do everything else. If you want a complete spreadsheet that can handle formulae, all you need to do is incorporate a simple expression parser.

The basics of the spreadsheet are three elements: the column (or cell), the row, and the sheet itself. Each column contains a piece of data and the information for formatting that piece of data for display. The column contains methods to copy itself, clear itself out, and modify the data or formatting information in itself. The row is simply an array of columns that makes up a single row of the spreadsheet. The Row class needs to be able to modify any existing column in the row, as well as add new columns and remove columns. A row should be able to return the contents of any given column within that row so that the end user can modify the contents directly.

Finally, the Spreadsheet class will contain an array of rows. This array knows nothing about the individual columns in the sheet, nor does it know anything about formatting or data. This data encapsulation is consistent with the object-oriented paradigm, certainly, but is also important in terms of being able to easily modify the basic layers of the system with minimal change to the upper layers.