Comp Sci Fixing C++ Card Class Errors in Visual C++ 6

  • Thread starter Thread starter Math Is Hard
  • Start date Start date
  • Tags Tags
    C++ Class Errors
AI Thread Summary
The discussion centers around resolving errors in a C++ Card class implementation using Visual C++ 6. The primary issue arises from the need to fully qualify the return type of member functions, specifically using `Card::Rank` instead of just `Rank`. Additionally, the friend function for outputting the card's abbreviation must be defined within the correct namespace to access private members. The conversation also touches on how to implement a Deck class that utilizes the Card class, including challenges with accessing private member functions and the need for operator overloading for assignment. Overall, participants share insights on C++ syntax and functionality while troubleshooting specific coding problems.
Math Is Hard
Staff Emeritus
Science Advisor
Gold Member
Messages
4,650
Reaction score
39
Hi. I am working on an assignment writing the implementation for a class of playing cards.
http://www.pic.ucla.edu/~nathan/cgi-bin/moin.cgi/la1#head-111d7fc9df65f327018fa94234ab0b23c0857e98
Here is the header file that we were provided.
Code:
//filename card.h
#ifndef CARD_H
#define CARD_H
#include <iostream>

namespace pic10b{
        class Card{
                friend std::ostream& operator<<(std::ostream& os, const Card& c);
        public:
                enum Rank {TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE};
                enum Suit {CLUB, DIAMOND, HEART, SPADE};
                Card(){rank = TWO; suit = CLUB;};
                Card( Rank r, Suit s);
                Card( const Card& c );
                Rank getRank() const;
                Suit getSuit() const;
                bool isFaceCard() const;
                std::string toString() const;
                bool operator<(const Card& c) const;
                bool operator>(const Card& c) const;
                bool operator<=(const Card& c) const;
                bool operator>=(const Card& c) const;
                bool operator==(const Card& c) const;
                bool operator!=(const Card& c) const;
        private:
                std::string abbr() const;
                Rank rank;      
                Suit suit;
        };

}
#endif
I have written two constructors and the getRank() and getSuit() member functions so far.
Code:
//filename card.cpp
#include "card.h"
using namespace pic10b;
using namespace std;

Card::Card(Rank r, Suit s)
{
	rank = r;
	suit = s;
}
                

Card::Card(const Card& c )
{
	rank = c.getRank();
	suit = c.getSuit();
}

           
Rank Card::getRank() const  //errors reference this line
{
	return rank;
}
             
Suit Card::getSuit() const
{
	return suit;
}
I am working in Visual C++ 6 and getting some errors:
error C2143: syntax error : missing ';' before 'tag::id'
error C2501: 'Rank' : missing storage-class or type specifiers
fatal error C1004: unexpected end of file found

and all reference the
Rank Card::getRank() const
line in my card.cpp file.
Am I missing something obvious? Thanks!
 
Last edited by a moderator:
Physics news on Phys.org
I also have a simple driver that I'm using:
Code:
#include<iostream>
#include "card.h"
#include<string>
#include<cstdlib>

using namespace pic10b;
using namespace std;

int main()
{        
        return 0;
}
just a stripped down version of my prof's to provide a main() function.
 
Last edited:
The problem is that the full name of that type is Card::Rank.

In the declaration Rank Card::getRank() const, you are not yet within the scope of Card when you are declaring the return type... so you have to fully qualify it as Card::Rank.


Actually, I fibbed slightly. The full name is pic10b::Card::Rank. But I guess that using directive means that you don't have to specify the pic10b:: there.


Oh, and as a plug for gcc, it figured out that you were trying to name a type (MSVC++ thought you were trying to declare a variable named Rank) and it emits the error:

error: `Rank' does not name a type
 
Last edited:
OMG! You RULE, Hurkyl! Thank you!
 
FWIW Borland C++ (an ancient version) let's this through with a warning:

Warning card.cpp 20: Use qualified name to access member type 'pic10b::Card::Rank'
Warning card.cpp 25: Use qualified name to access member type 'pic10b::Card::Suit'

Line 20 was your
Rank Card::getRank() const //errors reference this line

But we already knew CPP compilers are not written so that mortals can understand the error messages. Tell me something new... :rolleyes:
 
Thanks. I'm sure y'all haven't seen the last of me. I'll be back after I get into more trouble!
 
There's something that is confusing me. In my teacher's driver he makes a new card like so:
Code:
                int r = rand()%13;
                int s = rand()%4;
                cout << "Round " << i+1 <<": Drawing first random card...";
                Card::Suit S = Card::Suit(s);
                Card::Rank R = Card::Rank(r);
                Card c1(R, S);
                cout << "it's a " << c1.toString() << endl;

I don't really understand how Suit(s) works in
Card::Suit S = Card::Suit(s);
since Suit is a member variable and not a function. The parentheses confuse me.
I'm not clear on how it takes an int value and casts it as a Suit enum type. Is this just something you can do with enums?
Same question for Rank(r) of course.
 
Card::Suit isn't a variable, it's a type... and you're invoking one of its constructors.


Try out this piece of code:

std::cout << char(65) << std::endl;
 
OK, thanks. I guess I just haven't seen anything like that before.
 
  • #10
One last thing I am stuck on. He has this private member function that returns a string that is an abbreviation of the card.
If card c1 is a King of Clubs, the programmer can just do
cout << c1;
in main() and it will print "KC"
In the header, the function declaration looks like this:
Code:
private:
                std::string abbr() const;
I can't figure out how cout<< would know what to do, or how to implement this. Any hints?

I don't have any friends, so I figure it has to be one the member functions that calls it, but I don't know which one.
 
  • #11
Math Is Hard said:
I don't have any friends
Such is the life of a computer programmer. :cry:

Er, actually you do:

friend std::ostream& operator<<(std::ostream& os, const Card& c);

So if you write that function, it will be able to access the abbr() method.
 
  • #12
Hurkyl said:
Such is the life of a computer programmer. :cry:

Er, actually you do:

friend std::ostream& operator<<(std::ostream& os, const Card& c);

So if you write that function, it will be able to access the abbr() method.

:smile: :smile: :smile:
ayeee! I missed that. My eyeballs have gone south!
 
  • #13
rats! I still can't beat this thing into submission.
I wrote the friend function my implementation file like so:
Code:
std::ostream& operator<<(std::ostream& os, const Card& c)
{
	os<<c.abbr();
	return os;
}
and then wrote the abbr() private member function like this, just to test:
Code:
std::string Card::abbr() const
{
	string str = "KC";
	return str;
}
but I'm getting an error "error C2248: 'abbr' : cannot access private member declared in class 'pic10b::Card'"
 
  • #14
I have a guess, haven't tested it yet, though.


Your class specified ::pic10b::operator<< as its friend, but you wrote ::operator<<. You need to write that function in the pic10b namespace, not the global namespace.
 
  • #15
That was it! Thanks so much!:smile:
 
  • #16
For the next assignment, we are writing a Deck class which uses the Card class we created. I wrote the default constructor, but I am stuck on overloading the << to cout a deck, which is an array of 52 cards.
The assignment is here:
http://www.pic.ucla.edu/~nathan/cgi-bin/moin.cgi/sa5
I figure for every position in the array I need to get the card that's there to return it's string abbreviation. I think I need to loop and grab strings and concatenate into one long string to finally put into os (I think!) but I can't figure out how to do this.

When we overloaded the "<<" just to cout<< a single card I used this:
Code:
std::ostream& operator<<(std::ostream& os, const Card& c)
{
	os<<c.abbr();
	return os;
}
which called this:
Code:
std::string Card::abbr() const
{
 //this just returned a 2-letter string for 
//the card abbreviation based on 
//the enums for the rank and suit.
}
so I can't figure out how to get each abbreviation from the cards in the deck. Any thoughts? Thanks. All I have now is a modified version of the card << overloader for a test.

I'll put what I have below in the next post.
 
Last edited by a moderator:
  • #17
The Deck header:
Code:
#ifndef DECK_H
#define DECK_H
#include <iostream>
#include "card.h"
namespace pic10b{
        class Deck{
  public:
   Deck(); // constructor   
  friend std::ostream& operator<<(std::ostream& os, const Deck& d);
  private:
   Card deck[52];
  };
}
#endif

The deck.cpp
Code:
#include "card.h"
#include "deck.h"
#include <sstream>
#include <string>
using namespace pic10b;
using namespace std;

namespace pic10b{
Deck::Deck() // constructor
{  	 	
int i = 0;

	for(Card::Suit s = Card::CLUB; s < Card::SPADE; s++)
	{
		for(Card::Rank r = Card::TWO; r < Card::ACE; r++)
		{
		Card c(r,s);
		deck[i] = c;
		i++;
		}
	}

}


std::ostream& operator<<(std::ostream& os, const Deck& d)
 {	
	 os<<"Test";
	 return os;
 }
}
 
  • #18
I think I need to loop and grab strings and concatenate into one long string to finally put into os (I think!) but I can't figure out how to do this.
How about starting with an empty string and writing a loop where you grab strings and append them to your string, and then put it in os? :-p I don't know what part with which you're having trouble.

Incidentally, you can write to a stream as many times as you like; there's no need to do it with a single insertion.
 
  • #19
Hi Hurkyl, Sorry for not being more specific. What I can't figure out is how to return a string value out of a card that's in the deck. I can reference d[0] for the first card in the deck, but I am not sure what to do from there.
 
  • #20
IF your card value and card suit are members of the class...it should be easy...just return a string or a char[2] or a char*...note a returning variables does not always have ot e on the left side it could be in your parameter list.

...if they are not inputed you will require to pas sthe suit and value.
 
  • #21
Well, the expression deck[0] is of type Card, right?

(technically, it's of type Card const&, but that's a minor quibble)

Oooh, I understand your problem now. You want to call abbr, but it's inaccessible, meaning you can't accomplish your goal of building one gigantic string.

(technically, you can, in a very roundabout fashion. But let's ignore that too)

So, that just means you'll have to find some way to output cards without calling abbr.
























If only there already existed a function for outputting a card... :rolleyes:
 
  • #22
well, let's see.. the Card class has an overloaded << friend which grabs the abbreviation string from the private member function abbr(), but I have absolutely no idea how to use the << in any other way than cout<< in main(). Instead of printing it with cout<< how can I give it to the os that is returned in my Deck << operator?
 
  • #23
nebbermind. It was easier than I thought.
os<<d.deck[0];
 
  • #24
Yep! :smile:
 
  • #25
*sigh* I'm having trouble getting the deck shuffling function going. I tried making it a friend function.
Code:
//deck.h header
friend void shuffle(const Deck& d);
for the implementation I just tried to replace a card with another to test.
Code:
//in deck.cpp
void shuffle(const Deck& d)
{
	d.deck[1] = d.deck[51];
}
and then I tried making a new card and putting it in the deck
Code:
//in deck.cpp
void shuffle(const Deck& d)
{
	Card::Suit s = Card::CLUB;
	Card::Rank r = Card::TWO;
	Card c(r,s);
	d.deck[1]=c;
}
but for both I get error C2678: binary '=' : no operator defined which takes a left-hand operand of type 'const class pic10b::Card' (or there is no acceptable conversion)

Do I need to overload the = operator in my Card class? Or my Deck class? Both? I'm getting confused because in my Deck constructor I can use =.
Code:
Deck::Deck() // constructor
{  	 	
int i = 0;

for(Card::Suit s = Card::CLUB; s <= Card::SPADE; s++){
	for(Card::Rank r = Card::TWO; r <= Card::ACE; r++)  {
		Card c(r,s);
		deck[i] = c;
		i++;
	  }
     }
}
Thanks. I am tearing my hair out over this %@!#! assignment.:frown:
 
  • #26
The compiler automatically supplies your class with a default implementation of operator=.


Now, the compiler message gives you a big hint -- what sort of arguments would you expect operator= to take here? Is there anything suspicious about the types you actually passed to operator=?
 
  • #27
I'm expecting it to take a card, which it does in the constructor. Why won't it take it in the shuffle function, if the card is an element of the deck?
 
  • #28
Right, you want to assign to a Card object.

But you are assigning to a const Card object. Did you really mean to assign to a Card constant?
 
  • #29
oops!:redface:
 

Similar threads

Replies
2
Views
4K
Replies
1
Views
2K
Replies
1
Views
1K
Replies
2
Views
1K
Replies
8
Views
1K
Replies
2
Views
2K
Replies
1
Views
2K
Replies
3
Views
2K
Replies
3
Views
1K
Back
Top