Link to home
Start Free TrialLog in
Avatar of __fletcher__
__fletcher__

asked on

Class inheritance trouble.

I have a class Card.cc and CardPile.cc, which compiles and runs extremely well.  Now I want to make a class called CardDeck, which extends CardPile.  I want it to use the same state(which is a vector<const Card*>), and I also want it to have a seperate state(another vector<const Card*>) which will hold only that deck(i.e. I want to be able to add cards to the pile that the deck belongs to without changing the deck)This is what I have, and it's seg. faulting on me:

class CardDeck: public CardPile {

public:

CardDeck( ) {  
//here I create 52 cards
addCard(...);  //addCard is a method in CardPile that takes
          //a const Card* and adds it to the pile.
mySize( ) = 52;  //mySize() returns a reference to my state for size.

  }

size_t& mySize( ) { return _size; }

private:
 size_t _size;
};

why won't this work, or better yet, what do I have to change to make it work??
Avatar of Hoegje
Hoegje

mySize( ) = 52;  //mySize() returns a reference to my state for size.

 }

size_t& mySize( ) { return _size; }



that seems strange to me.

my_size() cannot be the left side of a "="sign, because that would be like assigning a number to the function ??

In order to help you more, you'll need to post more code, I guess.
Avatar of __fletcher__

ASKER

since the mySize() function returns a reference to my state, it's the same as me saying: _size = 52;
unfortunately there is no other relevant code that I can post other than a huge list of me creating 52 cards, one by one, then adding them all to the pile using addCard(...); statements.  The only other thing I can say is that I create and pass the cards like this:

CardDeck() {
Card aceOfSpade(Spades, Ace); //this is how my
                             //constructor for Cards works
addCard(&aceOfSpades);//pass in address, since it takes
                      //Card*'s as parameters.
... //52 times

}
perhaps u can say what the problem is? what errors etc.?

what phenomenon?
When I try to access members of the pile, it seg faults, and I can't figure out why.  The constructor is calling addCard 52 times, which I know from debugging attempts, and the constructor is access for CardPile as well, but when I try to later access cards from the pile, I get a seg fault.
(..and after going over my code a hundred thousand(exagerated) times, I'm 100% sure it's not the accessing that's the problem, it's the constructor.)
i'm not quite sure that calling a method in the constructor is safe...
ASKER CERTIFIED SOLUTION
Avatar of CoolBreeze
CoolBreeze

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Axter
Please post the complete code for CardDeck.
And put a comment next to the line of code that gives you the segment fault error.

We can help you better if we have the *complete* picture.
Unfortunately I can't post the complete code, because it's an assignment, and I don't want to make my code public for fear of committing a scholastic offense.  I can, however post my interfaces so far, so I'll do that, and I'll post the code that I have that's giving errors.  

class CardPile {
 
  typedef vector<const Card*> card_list;
  typedef size_t size_type;
  static const size_type npos = static_cast<size_type>(-1);
public:

  //Constructors/Destructors

  //The default constructor initializes an empty pile with size 0.
  CardPile();

  //This constructor will create a new instance of a CardPile with
  //the given vector of cards in the pile.
  CardPile(const vector<const Card*> & crdpile);

  //The copy constructor will create a new instance of the CardPile
  //based on the information in the argument, which is also an instance
  //of CardPile
  CardPile(const CardPile& oldCardPile);

  //The destructor is responsible for deallocating any space that has been
  //dynamically allocated by this class
  virtual ~CardPile();

  //The addCard method adds the given card to the bottom of the pile.
  void addCard(const Card* crd);

  //The addToTop method adds the given card to the top of the pile.
  virtual void addToTop(const Card* crd);

  //The addToBottom method adds the given card to the bottom of the pile.
  virtual void addToBottom(const Card* crd);

  //The addCards method adds the argument pile to the bottom of the pile.
  //It adds the cards in the argument pile, not the pile itself.
  virtual void addCards(const CardPile& newCards);

  //The addCardsToTop method adds a pile of cards to the top of the pile.
  //It adds the cards in the argument pile, not the pile itself.
  virtual void addCardsToTop(const CardPile& newCards);

  //The addCardsToBottom method is the same as addCards
  virtual void addCardsToBottom(const CardPile& newCards);

  //The shuffle method will shuffle the entire pile of cards.
  //If the pile is empty, no action is taken.
  void shuffle();

  //The shuffleSomeCards will shuffle the specified pile/sub-pile of cards in
  //the pile. i.e it will change the order of those cards in the pile.
  //The function will also shuffle the argument pile.
  //If the card_list argument is empty, no action is taken.
  void shuffleSomeCards(CardPile& cards);

  //The following remove methods will all take no action
  //if the pile of cards is empty and return a null pointer.

  //The remove method will remove and return the top card in the pile
  const Card* remove();

  //The topCard method returns the top card in the pile.
  const Card* topCard();

  //The dealCard is the same as topCard and remove methods except that
  //it adds the card to the specified pile.
  //The argument pile must exist, and if the pile is empty, then no
  //card is delt.
  const Card* dealCard(CardPile& crdpile);
 
  //The removeFromBottom will remove and return the bottom card in the pile
  const Card* removeBottom();
 
  //The bottomCard method returns the bottom card in the pile.
  const Card* bottomCard();

  //The removeCard method removes the argument card
  //from the pile. If the card appears more than once in the pile,
  //all instances of that card are removed(the actual card, not a
  //card with the same suit and face value)
  //If the card isn't in the pile, no action is taken.
  void removeCard(const Card* crd);

  //The dealNumCards method will deal the specified number of cards
  //off the top of the cardpile, and add it to the specified card pile.
  //The argument pile must exist, and if the pile is empty, then no
  //card is delt. It returns the "sub-pile" that will be dealt.
  CardPile dealNumCards(CardPile& crdpile, size_type numcards = npos);
 
  //The removeCardType method will all cards of that type from the pile.
  //i.e.if card1="ace of spades", removeCard( card1 ) will remove all
  //cards that are the "ace of spades" from the pile.
  //If the card isn't in the pile, no action is taken
  void removeCardType(const Card* crd);

  //The clear method will remove all the cards from the pile.
  //i.e. it will create a new pile with 0 elements.
  void clear();

  //The empty method returns true if the cardpile has no cards in it,
  //and false otherwise.
  bool empty() const;

  //The size and getSize methods will return the number of cards in
  //the pile
  size_type size() const;
  size_type getSize() const;

  //The find method returns the first instance of the card found in the pile
  //starting at pos, which is 0 by default.
  //npos is returned if the card is not found or if the pile is empty.
  size_type find(const Card* crd) const;

  //The findCard method returns the first instance of a card that matches
  //the suit and face value of the argument card starting at pos and searching
  //to the end of the pile..
  //npos is returned if the card is not found, or if the pile is empty.
  size_type findCard(const Card* crd, size_type pos = 0) const;

  //The operator= method is invoked when an instance of CardPile is assigned
  //to another CardPile.
  CardPile& operator=(const CardPile& crdpile);

  //The += method is the same as addCards and addCardsToBottom except that
  //it takes a CardPile as an argument instead of a vector, and the argument
  //cardpile will remain, but be empty when the method is finished.
  virtual CardPile& operator+=(CardPile& crdpile);

  //The operator== method returns true if the receiver CardPile is
  //identical in content to the argument CardPile
  bool operator==(const CardPile& crdpile) const;

  //The operator[] method returns a the Card* that is at pos in the pile.
  //No out of bounds checking is done with this function.
  const Card* operator[](size_type pos) const;

  //The at function is the same as the operator[] function except that it
  //throws an out_of_pile exception if memory outside the cardpile is accessed.
  const Card* at(size_type pos) const;

  //A function to swap 2 card's positions in the pile
  //swap takes no action if either card is not in the pile.
  //Throws an out_of_pile exception if attempt to access outside bounds of pile.
  void swap(size_type pos1, size_type pos2);

  //A function to sort the pile of cards, so that the Ace of Spades
  //is the first card, and the 2 of Diamonds is the last, sorting from
  //Ace to 2 for each suit going from Spades to Heards to Clubs to
  //Diamonds.
  void sortPile();

  //The subPile method will return a sub-Pile of the pile starting at pos
  //and having numcards cards.  The sub-pile of cards returned will
  //itself be a pile.  The old pile will remain unchanged. No action is taken
  //if numcards is not passed.
  //The method will throw an out_of_pile exception if pos is outside the
  //range of the pile.
  CardPile subPile(size_type pos = 0, size_type numcards = npos) const;

  //A getter for the card_list
  //const to be safe.  
  const card_list& getCards() const;

protected:

  //A getter for the size and card_list
  //protected, and const, to be safe
  const card_list& myCards() const;  
  const size_type & mySize() const;

private:

  //A function to randomly select a card from the pile
  //an return a reference to it.
  size_type randomCard();

  //To have access to my state without direct access.
  card_list& myCards();
  size_type & mySize();


  card_list _cards;
  size_type _size;

};

ostream& operator<<(ostream & os, const CardPile& crdpile);
//*****************The above is all CardPile.hh**********//
//*****************This class compiles and runs fine*****//



//********The following is all CardDeck.hh**************//

class CardDeck : public CardPile{
 
  typedef vector<const Card*> card_list;
  typedef size_t size_type;
  static const size_type npos = static_cast<size_type>(-1);
 

  public:
  //Constructors/Destructors

  //The default constructor will create a new instance of a CardDeck,
  //with the regular 52 cards any deck can have.  A deck can never have
  //more than 52 cards, but can have less.
  CardDeck();

  //The copy constructor will create a new instance of the CardDeck based
  //on the information in the argument, which is also an instance of CardDeck
  CardDeck(const CardDeck& oldDeck);

  //The destructor is responsible for deallocating any space that has been
  //dynamically allocated by this class.
  virtual ~CardDeck();

  //**For all add methods, the deck size can never exceed 52, and a card
  //will not be added if the caller attempts to add to a "full" deck.

  //The addToTop method adds the given card to the top of the pile.
  virtual void addToTop(const Card* crd);

  //The addToBottom method adds the given card to the bottom of the pile.
  virtual void addToBottom(const Card* crd);

  //The addCards method adds the argument pile to the bottom of the pile.
  //It adds the cards in the argument pile, not the pile itself.
  virtual void addCards(const CardPile& newCards);

  //The addCardsToTop method adds a pile of cards to the top of the pile.
  //It adds the cards in the argument pile, not the pile itself.
  virtual void addCardsToTop(const CardPile& newCards);

  //The addCardsToBottom method is the same as addCards
  virtual void addCardsToBottom(const CardPile& newCards);

  //The full method returns true if the deck has 52 cards, and false
  //otherwise
  bool full() const;

  //The += method is the same as addCards and addCardsToBottom except that
  //it takes a CardPile as an argument instead of a vector, and the argument
  //cardpile will remain, but be empty when the method is finished.
  virtual CardPile& operator+=(CardPile& crddeck);

protected:

  //A getter for the card_list
  //protected, and const, to be safe.  
  // const CardPile& myCards() const;
  const size_type & mySize() const;

private:
  /*
  //A function to randomly select a card from the pile
  //an return a reference to it.
  size_type randomCard();
   */
  //To have access to my state without direct access.
  //CardPile& myCards();
  size_type & mySize();

  size_type _size;
 
};


//****Then, in a CardDeck.cc file, I define those functions
//****But the only one I have code for so far is the constructor
//****And it compiles, but it seg faults when I do this in main:

CardDeck crddeck;
cout << crddeck << endl;  //I think it's here that it faults,
//because the operator<< in CardPile accesses individual
//cards, and I think that causes the seg. fault.

//I could create Card*'s in the constructor, but
//then how do I delete them in my destructor??

//Thanks
I also have a Card class with the following interface:

enum Suit_Type { Diamonds, Clubs, Hearts, Spades };
enum Face_Value { Two=2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace};


class Card {

public:

  //Constructors/Destructors
  //No default Constructor, since all cards have a suit and a face value

  //Constructor that creates a new instance of Card with the given suit
  //and face value.
  Card(const Suit_Type suit, const Face_Value value);

  //Copy Constructor creates a new instance of Card based on the information
  //in the argument, which is also an instance of Card.
  Card(const Card& oldCard);

  //The destructor, responsible for deallocating any space that has been
  //dynamically allocated by this class.
  ~Card();

  //The getSuit, and suit methods return the suit of the card.
  const Suit_Type getSuit() const;
  const Suit_Type suit() const;

  //The getValue, and value methods return the value of the card.
  const Face_Value getValue() const;
  const Face_Value value() const;

  //The operator= method is invoked when an instance of Card is assigned
  //another Card.
  const Card& operator=(const Card& crd);
 
  //The operator== method returns true if the receiver Card is
  //identical in content(i.e. has the same face value, and the same
  //suit) to the argument Card.
  bool operator==(const Card& crd) const;

  //The operator< method returns true if the receiver Card is smaller
  //than the argument card.  To determine this, Spades is the highest
  //valued suit, followed by Hearts, Clubs and Diamonds respectively.
  //Aces will be thought of as high cards.  Example:
  //
  //         The Ace of Spades is the HIGHEST card and is always greater
  //         than the other card(unless they are equal).
  //
  //         The Two of Diamonds is the LOWEST card and is always less than
  //         the other card(unless they are equal).
  //
  //         The Queen of Hearts IS LESS THAN the 2 of Spades.
  //         The Queen of Hearts IS NOT LESS THAN the 5 of Clubs.
  bool operator<(const Card& crd) const;

  //The operator> method returns true if the receiver Card is greater
  //than the argument card.  It uses the same rules as operator< to
  //determine truth or falsity.  The main reason for this function is
  //to facilitate sorting when cards are in a pile/deck/hand
  bool operator>(const Card& crd) const;

  //The operator<= method returns true if the receiver Card is smaller
  //than OR equal to the argument Card.  It uses the same rules as
  //operator< and operator== to determine truth or falsity.
  bool operator<=(const Card& crd) const;

  //The operator>= method returns true if the receiver Card is greater
  //than OR equal to the argument Card.  It uses the same rules as
  //operator> and operator== to determine truth or falsity.
  //The main reason for this method is to facilitate sorting when
  //cards are in a pile/deck/hand
  bool operator>=(const Card& crd) const;

private:

  //The changeCard method changes the value and the suit of the card to
  //the arguments passed.  This may be useful later on for shuffleing a
  //deck of cards.
  void changeCard(const Suit_Type suit, const Face_Value value);

  //Two setters used to initialize a card.
  void setSuit(Suit_Type suit);
  void setValue(Face_Value value);

  //Two states for a Card, both are enum constants.  They represent the
  //suit and the face value of the card respectively.  
  Suit_Type _suit;
  Face_Value _value;

};


//method used to make a card printable in cout statements.
ostream& operator<<(ostream & os, const Card& crd);
CoolBreeze was right, I needed to make them pointers so that they were not local, but how do I destruct them now?

Are the pointers dynamically allocated, or are they placed on the stack and I don't need to worry about them.  Thanks for your help!!
by making them pointers, u had to have a way to destruct the cards u stored in the pile, that is have a method in CardDeck or CardPile to destroy the cards. That's one of the reason y u are using CardPile, to collate the cards together. otherwise, u would create each card individually and use them already.

u have a vector<const Card*>, so in CardPile's destructor, u can do this:

vector<const Card*> cardpile;

for (int i=cardpile.size()-1; i>=0; i--) {
  delete[] cardpile[i];
}
FYI:
You should ALWAYS nullify a pointer after it has been deleted.
Not doing so can lead to undefined behavoir, if you later try to use it.
Use the follow DeleteObject class, you can delete, nullify, and remove the pointer from the container in one line of code.

class DeleteObject
{
public:
     template<typename T>
          operator()(T& ptr)
     {
          delete &*ptr;
          ptr = NULL;
          return true;
     }
};

vector<const Card*> cardpile;

//***** Delete, nullify, and remove pointer *******
cardpile.erase(remove_if(cardpile.begin(), cardpile.end(),DeleteObject()), cardpile.end());