Skip to main content

How To Think Like a Computer Scientist C++ Edition The Pretext Interactive Version

Section 13.5 Deck member functions

Now that we have a Deck object, it makes sense to put all the functions that pertain to Decks in the Deck structure definition. Looking at the functions we have written so far, one obvious candidate is printDeck (Listing 12.7.1). Here’s how it looks, rewritten as a Deck member function:
void Deck::print() const {
  for (size_t i = 0; i < cards.size(); i++) {
    cards[i].print();
  }
}
As usual, we can refer to the instance variables of the current object without using dot notation.
Listing 13.5.1. This active code prints out the deck of cards like in the previous section. Notice we can just use deck.print() to print out the deck instead of writing a for loop in main.
For some of the other functions, it is not obvious whether they should be member functions of Card, member functions of Deck, or nonmember functions that take Cards and Decks as parameters. For example, the version of find in the previous chapter takes a Card and a Deck as arguments, but you could reasonably make it a member function of either type. As an exercise, rewrite find as a Deck member function that takes a Card as a parameter.
Writing find as a Card member function is a little tricky. Here’s my version:
int Card::find(const Deck& deck) const {
  for (size_t i = 0; i < deck.cards.size(); i++) {
    if (equals(deck.cards[i], *this)) return i;
  }
  return -1;
}
The first trick is that we have to use the keyword this to refer to the Card the function is invoked on.
The second trick is that C++ does not make it easy to write structure definitions that refer to each other. The problem is that when the compiler is reading the first structure definition, it doesn’t know about the second one yet.
One solution is to declare Deck before Card and then define Deck afterwards:
// declare that Deck is a structure, without defining it
struct Deck;

// that way we can refer to it in the definition of Card
struct Card {
  int suit, rank;

  Card();
  Card(int s, int r);

  void print() const;
  bool isGreater(const Card& c2) const;
  int find(const Deck& deck) const;
};

// and then later we provide the definition of Deck
struct Deck {
  vector<Card> cards;

  Deck();
  Deck(int n);
  void print() const;
  int find(const Card& card) const;
};

Checkpoint 13.5.1.

Multiple Response: What are some tricks we can use to write find as a Card member function?
  • Use the keyword this.
  • We use this to refer to the Card that the function is invoked on.
  • Define Deck before Card.
  • We don’t have to define Deck before Card.
  • Pass a Card parameter in the Card member function find.
  • What do we pass as a parameter in find?
  • Declare Deck before Card and then define Deck afterwards.
  • This is how we implemented our code!

Checkpoint 13.5.2.

Write find as a Deck member function that takes a Card as a parameter.
Listing 13.5.2. This active code uses the Deck::find function you just built.
You have attempted 1 of 5 activities on this page.