2.8. Is your class const-correct?

In C++, we use the keyword const to declare constants. But it also has two other important uses:

  1. indicating what formal parameters a function will look at, but promises not to change

  2. indicating which member functions don't change the object they are applied to

These last two uses are important for a number of reasons

definition

A class is const-correct if

  1. Any formal function parameter that will not be changed by the function is passed by copy or as a const reference (const &).

  2. Every member function that does not alter the object it's applied to is declared as a const member.

Const and Member Functions

class Point {
public:
   double x;
   double y;

   double distanceFrom (Point p);
};

  • How many parameters does distanceFrom have?

How Many Parameters?

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);
    };
    
    

Protecting Parameters

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?

Protecting *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

Const member Functions

As a general rule, any member functions that, logically, do not change the object they are applied to, should be marked as const.

Const Correctness: BidCollection

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;
}

Exercise

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:

(no threads at this time)