Card class for card games
If you are going to go to the trouble of creating Rank and Suit enum then use them.

Card( int rank, int suit ) throw(std::range_error)


I would have done

Card(Rank rank,Suit suit )


That way you can't accidentally go: Card(Card::Hearts,2) The compiler type checking will catch this at compiletime. Just use the enums all through your code. C++ is a strongly typed language use the compiler to catch your errors.

The exception specifications have been deprecated. They were mostly useless anyway (if you fail and throw an illegal exception it causes your application to terminate without unwinding the stack). So in general don't use them. For the one case where they are usfull (no throw specifications) they are good but I use them more as documentation to remind me that I should make sure the method does not throw.

But yes the constructor should throw an exception if it gets a value outside the expected range. There is no point in allowing an invalid object to propagate threw your code it will just cause problems with your invariants.

Prefer to use the initializer list rather than initializing variables in the constructor.

Card(Rank rank, Suit suit)
    : m_rank(rank)
    , m_suit(suit)


Again another place that it would have been nice to use the enum to make the code more eadable:

        if( rank &lt; 1 || rank &gt; 13 ) {


Try:

        if( rank &lt; Ace || rank &gt; King ) {


Hate getters/setter they spoil encapsulation. Do you really need to get the values of the card? Any operation that manipulates the card is usually a method on the card or a friendly class.

int rank() const { return m_rank; }
int suit() const { return m_suit; }


Don't try and write C++ like Java. We don;t need a string function. It is much more preferable (and flexable) to write an output (and probably input) stream operator.

std::string str() const
{
        return std::string( Ranks[m_rank] + Suits[m_suit] );
}


I would have done:

friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; stream, Card const&amp; card)
{
    return stream &lt;&lt; card.Ranks[card.m_rank] &lt;&lt; card.Suits[card.m_suit];
}


Adding Cards to a deck. (Based on comment below)

#include &lt;vector&gt;

class Card
{
    public:
        enum Ranks { Ace = 1, Ten = 10, Jack, Queen, King };
        enum Suits { Spades, Hearts, Diamonds, Clubs };

        Card(Ranks rank, Suits suit){}
};

// Need to add the ++ operators for Ranks/Suits
Card::Ranks&amp; operator++(Card::Ranks&amp; r)
{
    return r = Card::Ranks(static_cast&lt;int&gt;(r)+1);
}
Card::Suits&amp; operator++(Card::Suits&amp; s)
{
    return s = Card::Suits(static_cast&lt;int&gt;(s)+1);
}



int main()
{
    std::vector&lt;Card&gt;   deck;

    // Does not look that verbose to me.
    for(Card::Ranks rank=Card::Ace;rank &lt;= Card::King;++rank)
    {
        for(Card::Suits suit=Card::Spades;suit &lt;= Card::Clubs;++suit)
        {
            deck.push_back(Card(rank, suit));
        }
    }

    // Compared to 
    for(int rank=Card::Ace;rank &lt;= Card::King;++rank)
    {
        for(int suit=Card::Spades;suit &lt;= Card::Clubs;++suit)
        {
            deck.push_back(Card(rank, suit));
        }
    }
}