Online Book Reader

Home Category

Professional C__ - Marc Gregoire [104]

By Root 1220 0
In addition, there are some tricky, but interesting, things you can do with operator overloading that you might not anticipate at first. The STL uses operator overloading extensively. Chapter 18 explains how and when to overload the rest of the operators. Chapters 11 to 17 cover the STL.

BUILDING STABLE INTERFACES


Now that you understand all the gory syntax of writing classes in C++, it helps to revisit the design principles from Chapters 3 and 4. Classes are the main unit of abstraction in C++. You should apply the principles of abstraction to your classes to separate the interface from the implementation as much as possible. Specifically, you should make all data members protected or private and provide getter and setter methods for them. This is how the SpreadsheetCell class is implemented. mValue and mString are protected; set(), getValue(), and getString() set and retrieve those values. That way you can keep mValue and mString in synch internally without worrying about clients delving in and changing those values.

Using Interface and Implementation Classes

Even with the preceding measures and the best design principles, the C++ language is fundamentally unfriendly to the principle of abstraction. The syntax requires you to combine your public interfaces and private (or protected) data members and methods together in one class definition, thereby exposing some of the internal implementation details of the class to its clients. The downside of this is that if you have to add new non-public methods or data members to your class, all the clients of the class have to be recompiled. This can become a burden in bigger projects.

The good news is that you can make your interfaces a lot cleaner and hide all implementation details, resulting in stable interfaces. The bad news is that it takes a bit of hacking. The basic principle is to define two classes for every class you want to write: the interface class and the implementation class. The implementation class is identical to the class you would have written if you were not taking this approach. The interface class presents public methods identical to those of the implementation class, but it only has one data member: a pointer to an implementation class object. The interface class method implementations simply call the equivalent methods on the implementation class object. The result of this is that no matter how the implementation changes, it has no impact on the public interface class. This reduces the need for recompilation. None of the clients that use the interface class need to be recompiled if the implementation (and only the implementation) changes.

To use this approach with the Spreadsheet class, simply rename the old Spreadsheet class to SpreadsheetImpl. Here is the new SpreadsheetImpl class (which is identical to the old Spreadsheet class, but with a different name):

#include "SpreadsheetCell.h"

class SpreadsheetApplication; // Forward declaration

class SpreadsheetImpl

{

public:

SpreadsheetImpl(const SpreadsheetApplication& theApp,

int inWidth = kMaxWidth, int inHeight = kMaxHeight);

SpreadsheetImpl(const SpreadsheetImpl& src);

~SpreadsheetImpl();

SpreadsheetImpl &operator=(const SpreadsheetImpl& rhs);

void setCellAt(int x, int y, const SpreadsheetCell& inCell);

SpreadsheetCell getCellAt(int x, int y);

int getId() const;

static const int kMaxHeight = 100;

static const int kMaxWidth = 100;

protected:

bool inRange(int val, int upper);

void copyFrom(const SpreadsheetImpl& src);

int mWidth, mHeight;

int mId;

SpreadsheetCell** mCells;

const SpreadsheetApplication& mTheApp;

static int sCounter;

};

Code snippet from SeparateImpl\SpreadsheetImpl.h

Then define a new Spreadsheet class that looks like this:

#include "SpreadsheetCell.h"

// Forward declarations

class SpreadsheetImpl;

class SpreadsheetApplication;

class Spreadsheet

{

public:

Spreadsheet(const SpreadsheetApplication& theApp, int inWidth,

int inHeight);

Spreadsheet(const SpreadsheetApplication& theApp);

Spreadsheet(const Spreadsheet& src);

~Spreadsheet();

Spreadsheet&

Return Main Page Previous Page Next Page

®Online Book Reader