Online Book Reader

Home Category

Professional C__ - Marc Gregoire [95]

By Root 1144 0
// OK

const SpreadsheetCell& anotherCell = myCell;

cout << anotherCell.getValue() << endl; // OK

anotherCell.setString("6"); // Compilation Error!

Code snippet from SpreadsheetCellMethods\SpreadsheetCellTest.cpp

You should get into the habit of declaring const all methods that don’t modify the object so that you can use references to const objects in your program.

Note that const objects can still be destroyed, and their destructor can be called. You shouldn’t try to mark the destructor const.

mutable Data Members

Sometimes you write a method that is “logically” const but happens to change a data member of the object. This modification has no effect on any user-visible data, but is technically a change, so the compiler won’t let you declare the method const. For example, suppose that you want to profile your spreadsheet application to obtain info about how often data is being read. A crude way to do this would be to add a counter to the SpreadsheetCell class that counts each call to getValue() or getString(). Unfortunately, that makes those methods non-const in the compiler’s eyes, which is not what you intended. The solution is to make your new counter variable mutable, which tells the compiler that it’s okay to change it in a const method. Here is the new SpreadsheetCell class definition:

class SpreadsheetCell

{

// Omitted for brevity

protected:

double mValue;

string mString;

mutable int mNumAccesses = 0;

};

Code snippet from SpreadsheetCellMethods\SpreadsheetCell.h

Here are the definitions for getValue() and getString():

double SpreadsheetCell::getValue() const

{

mNumAccesses++;

return mValue;

}

string SpreadsheetCell::getString() const

{

mNumAccesses++;

return mString;

}

Code snippet from SpreadsheetCellMethods\SpreadsheetCell.h

Method Overloading

You’ve already noticed that you can write multiple constructors in a class, all of which have the same name. These constructors differ only in the number or types of their parameters. You can do the same thing for any method or function in C++. Specifically, you can overload the function or method name by using it for multiple functions, as long as the number or types of the parameters differ. For example, in the SpreadsheetCell class you could rename both setString() and setValue() to set(). The class definition now looks like this:

class SpreadsheetCell

{

public:

// Omitted for brevity

void set(double inValue);

void set(const string& inString);

// Omitted for brevity

};

Code snippet from SpreadsheetCellMethods\SpreadsheetCell.h

The implementations of the set() methods stay the same. Note that the double constructor that previously called setValue() must now call set(). When you write code to call set(), the compiler determines which instance to call based on the parameter you pass: If you pass a string the compiler calls the string instance; if you pass a double the compiler calls the double instance. This is called overload resolution.

You might be tempted to do the same thing for getValue() and getString(): Rename each of them to get(). However, that does not compile. C++ does not allow you to overload a method name based only on the return type of the method because in many cases it would be impossible for the compiler to determine which instance of the method to call. For example, if the return value of the method is not captured anywhere, the compiler has no way to tell which instance of the method you wanted.

Note also that you can overload a method based on const. That is, you can write two methods with the same name and same parameters, one of which is declared const and one of which is not. The compiler will call the const method if you have a const object and the non-const method if you have a non-const object.

Overloaded methods can be explicitly deleted, which can be used to disallow calling a member function with particular parameters. For example, suppose you have the following class:

class MyClass

{

public:

void foo(int i);

};

The foo() method can be called as follows:

MyClass c;

c.foo(123);

c.foo(1.23);

Return Main Page Previous Page Next Page

®Online Book Reader