In C++, we use the keyword const
to declare
constants. But it also has two other important uses:
indicating what formal parameters a function will look at, but promises not to change
indicating which member functions don't change the object they are applied to
These last two uses are important for a number of reasons
This information often helps make it easier for programmers to understand the expected behavior of a function.
The compiler may be able to use this information to generate more efficient code.
This information allows the compiler to detect many potential programming mistakes.
A class is const-correct if
Any formal function parameter that will not be changed by
the function is passed by copy or as a const reference
(const &
).
Every member function that does not alter the object it's applied to is declared as a const member.
class Point { public: double x; double y; double distanceFrom (Point p); };
How many parameters does distanceFrom
have?
class Point { public: double x; double y; double distanceFrom (Point p); };
When we call it, we do so like this:
double dist = p1.distanceFrom(p2);
which shows that there are clearly two parameters, one on the left and one in the parentheses.
The implicit parameter is called this
and has
data type "pointer-to-whatever-class-this-is":
class Point { public: double x; double y; double distanceFrom (/* Point* this,*/ Point p); };
class Point { public: double x; double y; double distanceFrom (/* Point* this,*/ Point p); };
If we want to promise that distanceFrom
will
not change p
, we do so by passing p
by
value or by const reference:
double distanceFrom (/* Point* this,*/ const Point& p);
How do we promise not to change *this
?
class Point { public: double x; double y; double distanceFrom (/* Point* this,*/ const Point& p) <[+]>const<[-]>; };
Would like to declare this
as const
Point*
But there's no place to do so
So the C++ language designers decided to stick it on to the end
Called a const member function
As a general rule, any member functions that, logically, do not
change the object they are applied to, should be marked as
const
.
Passed by copy, passed by const ref, & const member functions
class BidCollection { static int MaxSize; int size; Bid* elements; // array of bids public: static void setMaxSize(int max); // Establish the common max size used for all bid collections // Must be called BEFORE any collections have been constructed /** * Create a collection capable of holding the indicated number of bids */ BidCollection (); ~BidCollection (); // Access to attributes int getMaxSize() const {return MaxSize;} int getSize() const {return size;} // Access to individual elements const Bid& get(int index) const {return elements[i];} // Collection operations void addInTimeOrder (const Bid& value); // Adds this bid into a position such that // all bids are ordered by the time the bid was placed //Pre: getSize() < getMaxSize() void remove (int index); // Remove the bid at the indicated position //Pre: 0 <= index < getSize() /** * Read all bids from the indicated file */ void readBids (std::string fileName); }; ⋮ // in the .cpp file: int BidCollection::MaxSize = 1000; void BidCollection::setMaxSize(int max) { maxSize = max; }
What changes would you make so that Bid
would be
const-correct?
class Bid {
static int bidCounter;
int id;
std::string bidderName;
double amount;
std::string itemName;
Time bidPlacedAt;
public:
Bid (std::string bidder, double amt,
std::string item, Time placedAt);
std::string getBidder() {return bidderName;}
double getAmount() {return amount;}
std::string getItem() {return itemName;}
Time getTimePlacedAt() {return bidPlacedAt;}
int getID() {return id;}
};
⋮
int Bid::bidCounter = 0;
Bid::Bid (std::string bidder, double amt,
std::string item, Time placedAt);
: bidderName(bidder), amount(amt),
itemName(item), bidPlacedAt(placedAt)
{
++bidCounter;
id = bidCounter;
}
Discuss This Page: