Professional C__ - Marc Gregoire [92]
int Spreadsheet::sCounter = 0;
Code snippet from SpreadsheetDataMembers\Spreadsheet.cpp
This code appears outside of any function or method bodies. It’s almost like declaring a global variable, except that the Spreadsheet:: scope resolution specifies that it’s part of the Spreadsheet class.
Accessing static Data Members within Class Methods
You can use static data members as if they were regular data members from within class methods. For example, you might want to create an mId member of the Spreadsheet class and initialize it from the sCounter member in the Spreadsheet constructor. Here is the Spreadsheet class definition with an mId member:
class Spreadsheet
{
public:
// Omitted for brevity
int getId() const;
protected:
// Omitted for brevity
static int sCounter = 0;
int mId;
};
Code snippet from SpreadsheetDataMembers\Spreadsheet.h
Here is an implementation of the Spreadsheet constructor that assigns the initial ID:
Spreadsheet::Spreadsheet(int inWidth, int inHeight) :
mWidth(inWidth), mHeight(inHeight)
{
mId = sCounter++;
mCells = new SpreadsheetCell* [mWidth];
for (int i = 0; i < mWidth; i++) {
mCells[i] = new SpreadsheetCell[mHeight];
}
}
Code snippet from SpreadsheetDataMembers\Spreadsheet.cpp
As you can see, the constructor can access sCounter as if it were a normal member. Remember to assign an ID in the copy constructor as well:
Spreadsheet::Spreadsheet(const Spreadsheet& src)
{
mId = sCounter++;
copyFrom(src);
}
Code snippet from SpreadsheetDataMembers\Spreadsheet.cpp
You should not copy the ID in the assignment operator. Once an ID is assigned to an object it should never change.
Accessing static Data Members Outside Methods
Access control specifiers apply to static data members: sCounter is protected, so it cannot be accessed from outside class methods. If sCounter was public, you could access it from outside class methods by specifying that the variable is part of the Spreadsheet class with the :: scope resolution operator:
int c = Spreadsheet::sCounter;
However, it’s not recommended to have public data members. You should grant access through public get/set methods. If you want to grant access to a static data member, you need to implement static get/set methods, which are explained later in this chapter.
const Data Members
Data members in your class can be declared const, meaning they can’t be changed after they are created and initialized. Constants almost never make sense at the object level, so const data members are usually static as well. You should use static const data members in place of global constants when the constants apply only to the class. For example, you might want to specify a maximum height and width for spreadsheets. If the user tries to construct a spreadsheet with a greater height or width than the maximum, the maximum is used instead. You can make the max height and width static const members of the Spreadsheet class:
class Spreadsheet
{
public:
// Omitted for brevity
static const int kMaxHeight = 100;
static const int kMaxWidth = 100;
};
Code snippet from SpreadsheetDataMembers\Spreadsheet.h
You can use these new constants in your constructor as shown in the following section of code (note the use of the ternary operator):
Spreadsheet::Spreadsheet(int inWidth, int inHeight) :
mWidth(inWidth < kMaxWidth ? inWidth : kMaxWidth),
mHeight(inHeight < kMaxHeight ? inHeight : kMaxHeight)
{
mId = sCounter++;
mCells = new SpreadsheetCell* [mWidth];
for (int i = 0; i < mWidth; i++) {
mCells[i] = new SpreadsheetCell[mHeight];
}
}
Code snippet from SpreadsheetDataMembers\Spreadsheet.cpp
Instead of automatically clamping the width and height to their maximum, you could also decide to throw an exception when the width or height exceed their maximum. However, the destructor will not be called when you throw an exception