Online Book Reader

Home Category

Professional C__ - Marc Gregoire [117]

By Root 1443 0
class has nothing to set. This approach still doesn’t feel right, however. Ideally, there should never be an object that is an instance of the base class. Calling set() should always have an effect because it should always be called on either a DoubleSpreadsheetCell or a StringSpreadsheetCell. A good solution will enforce this constraint.

The preceding code declares a virtual destructor for the SpreadsheetCell class. If you don’t do this, the compiler will generate a default destructor for you but a non-virtual one. That means if you don’t declare the virtual destructor yourself, you might encounter problems with destruction of subclasses through pointers or references as explained earlier in this chapter.

Pure Virtual Methods and Abstract Base Classes

Pure virtual methods are methods that are explicitly undefined in the class definition. By making a method pure virtual, you are telling the compiler that no definition for the method exists in the current class. Thus, the class is said to be abstract because no other code will be able to instantiate it. The compiler enforces the fact that if a class contains one or more pure virtual methods, it can never be used to construct an object of that type.

There is a special syntax for designating a pure virtual method. The method declaration is followed by =0. No code needs to be written in the .cpp file, and any attempt to write code will cause a compiler error.

class SpreadsheetCell

{

public:

SpreadsheetCell();

virtual ~SpreadsheetCell();

virtual void set(const std::string& inString) = 0;

virtual std::string getString() const = 0;

};

Code snippet from PolymorphicSpreadsheet\SpreadsheetCell.h

Now that the base class is an abstract class, it is impossible to create a SpreadsheetCell object. The following code will not compile, and will give an error such as Cannot declare object of type 'SpreadsheetCell' because one or more virtual functions are abstract:

SpreadsheetCell cell; // BUG! Attempts creating abstract class instance

However, the following code will compile:

SpreadsheetCell* ptr;

This works because it will require instantiating a derived class of the abstract superclass, for example:

ptr = new StringSpreadsheetCell();

An abstract class provides a way to prevent other code from instantiating an object directly, as opposed to one of its subclasses.

Base Class Source Code

There is not much code required for SpreadsheetCell.cpp. As the class was defined, most of the methods are pure virtual — there is no definition to give. All that is left is the constructor and destructor. For this example, the constructor is implemented just as a placeholder in case initialization needs to happen in the future. However, the virtual destructor is required as was explained earlier.

SpreadsheetCell::SpreadsheetCell() { }

SpreadsheetCell::~SpreadsheetCell() { }

Code snippet from PolymorphicSpreadsheet\SpreadsheetCell.cpp

The Individual Subclasses

Writing the StringSpreadsheetCell and DoubleSpreadsheetCell classes is just a matter of implementing the functionality that is defined in the parent. Because we want clients to be able to instantiate and work with string cells and double cells, the cells can’t be abstract — they must implement all of the pure virtual methods inherited from their parent.

String Spreadsheet Cell Class Definition

The first step in writing the class definition of StringSpreadsheetCell is to subclass SpreadsheetCell:

class StringSpreadsheetCell : public SpreadsheetCell

{

Code snippet from PolymorphicSpreadsheet\StringSpreadsheetCell.h

You want to initialize the data value of the StringSpreadsheetCell to “#NOVALUE” to indicate that the value has not been set. The compiler generated default constructor will call the default string constructor for mValue which will set the initial value to the empty string, “”. So, you need to provide an explicit default constructor and initialize the value yourself.

public:

StringSpreadsheetCell();

Next, the inherited pure virtual methods are overridden, this time without being set to zero:

virtual

Return Main Page Previous Page Next Page

®Online Book Reader