Section 8 - The Card Class

1A.8.1  The Card Class

scenic powerlineWe are now ready to show the entire Card class and a small test program.  Note the order of the components:

  1. The class prototype(s) are first
  2. The main() method is second
  3. The class method definitions are last

For programs in which all the code resides in a single .cpp file, this is the order in which you should do things.  Also, we do not ever define class methods in-line, i.e., in the class prototypes except for one-line accessors.  This destroys the readability of the class prototype.  I will take off points if I see that in your code, so please don't do it. I did not define the accessors below in-line, but I might have; as I say, that would be the one case when in-line is okay.

Paste the following into a simple console application and compile and run it.  Make changes until you feel like you can control it.

1A.8.2  Listing

#include <string>
#include <iostream>
#include <sstream>
#include <cctype>

using namespace std;

enum Suit { clubs, diamonds, hearts, spades };

// class Card prototype -----------------------
class Card
{
private:
    char value;
    Suit suit;

public:
    Card(char value = 'A', Suit suit = spades);
    string toString();
    bool set(char value = 'A', Suit suit = spades);
    char getVal();
    Suit getSuit();
};  // end of class Card prototype --------------

int main()
{
    Card card1, card2('5'), card3('9', hearts),
    card4('j', clubs), card5('1', diamonds);

    if ( ! card1.set(2, clubs) )
        cout << "incorrect value (2, clubs) passed to card::set()\n\n";
    if ( ! card1.set('2', clubs) )
        cout << "incorrect value ('2', clubs) passed to card::set()\n\n";

    cout << card1.toString() << endl << card2.toString() << endl <<
    card3.toString() << endl << card4.toString() << endl
    << card5.toString() << endl<< endl;

    card1 = card4;

    // test assignment operator for objects
    cout << "after assigning card4 to card1:\n";
    cout << card1.toString() << endl << card4.toString()
    <<  endl << endl;

    // now notice the assignment operator is not a reference copy (like Java/C#)
    card1.set();
    cout << "after changing card1:\n";
    cout << card1.toString() << endl << card4.toString()
    <<  endl << endl;

    cout << "after assigning card4 to card1:\n";
    cout << card1.toString() << endl << card4.toString()
    <<  endl << endl;
    return 0;
}

// beginning of Card method definitions -------------

// constructor
Card::Card(char value, Suit suit)
{
// if not valid, set to Ace of Spades
if ( !set(value, suit) )
set('A', spades);
}

// stringizer
string Card::toString()
{
string retVal;
char strVal[2];

// convert char to a CString
strVal[0] = value;
strVal[1] = '\0';

// convert from CString to s-c string
retVal = string(strVal);

if (suit == spades)
retVal += " of Spades";
else if (suit == hearts)
retVal += " of Hearts";
else if (suit == diamonds)
retVal += " of Diamonds";
else if (suit == clubs)
retVal += " of Clubs";

return retVal;
}

// mutator
bool Card::set(char value, Suit suit)
{
char upVal;

// convert to uppercase to simplify (need #include <cctype>)
upVal = toupper((int)value);

// check for validity
if (
upVal == 'A' || upVal == 'K'
|| upVal == 'Q' || upVal == 'J'
|| upVal == 'T'
|| (upVal >= '2' && upVal <= '9')
)
{
this->suit = suit;
this->value = upVal;
return true;
}
else
return false;
}

// accessors
char Card::getVal()
{
return value;
}

Suit Card::getSuit()
{
return suit;
}
// end of Card method definitions  --------------

This example makes use of some of the tools we presented in the recent sections. Many of these concepts are review for you, but even if they are new, this should be a relatively easy program to learn and understand.  This is a good test to determine whether or not you are taking this course with the proper prerequisites.

In particular, make sure you understand the comment and output surrounding the test of the assignment operator between objects. In C++ this is a member-wise copy resulting in a distinct clone, not an assignment between pointers or references, which would have resulted in both variables referring to the same object.

In a couple days you can read the second lesson of this week. Until then, welcome back to C++.  We are going to have fun this quarter.