0

Edit :

  1. The problem is in the GoFish.h file, in the constructor to be specific, where it is trying to instantiate the players object.

  2. The compiler throws the following error message : no member named 'noOfBooks' in 'Player'

GoFish() {players = new GoFishPlayer[2];} // Instantiate two players

Object Slicing seems to be one of the most ambiguous concepts in OOP for beginners. I have been working on this card game in C++, where I have a base class called, Player and a derived class called GoFishPlayer. When trying to access the methods of a GoFishPlayer object referenced back to a Player Object, the program tends to slice off the specific methods and attributes for the derived class, thus making it a clone of the base object. Is there any way to overcome this problem?

Game.h

Abstract class Game : which forms the foundation for both the games - GoFish and CrazyEights

class Game {

protected:
Deck* deck;
Player* players;
int player_id;

public:
Game(){
    deck = Deck::get_DeckInstance(); // Get Singleton instance
    player_id = choosePlayer();
    players = NULL;
}
....
}

GoFish.h

Derived Class GoFish - The Problem is here in the constructor when I am trying to instantiate a Player object derived from the Game Class

class GoFish : public Game{

static GoFish* goFish;
GoFish() {players = new GoFishPlayer[2];} // Instantiate two players

public:
static GoFish* get_GoFishInstance() {
    if(goFish == NULL)
        goFish = new GoFish();

    return goFish;
}

Player.h

class Player{

protected:
std::string playerName;
Hand hand;
bool win;

public:
Player(){ 
    playerName = "Computer"; // Sets default AI name to Computer
    hand = Hand(); // Instatiate the hand object
    win = false;
}
....

GoFishPlayer.h

class GoFishPlayer : public Player {

private:
std::vector <int> books;
int no_of_books;

public:
GoFishPlayer() {
    no_of_books = 0;
    books.resize(13);
}

int noOfBooks(){return no_of_books;}
void booksScored() {no_of_books++;}

bool checkHand() {}
....
Luv
  • 44
  • 6

1 Answers1

1

The wording of your question seems ambiguous to me but as best as I understand you're trying to access methods of GoFishPlayer through a reference to a Player object? This isn't a problem caused by object slicing, it's just how polymorphism works.

You need to cast the reference of the Player object so that it becomes a reference to a GoFishPlayer object.

class Parent
{
    public:
        void foo() { std::cout << "I'm a parent" << std::endl; }
};

class Derived : public Parent
{
    public:
        void bar() { std::cout << "I'm a derived" << std::endl; }
};


int main()
{
    Derived d;

    // reference to a derived class stored as a prent reference
    // you can't access derived methods through this
    Parent& p_ref = d;
    // this won't work
    // p_ref.bar();

    Derived& d_ref = static_cast<Derived&>(p_ref);
    // this works
    d_ref.bar();
}

This only works if you definitely know that p_ref is actually of type Derived, or that it is of a type that inherits from Derived. If you can't be sure you need to do a runtime check using dynamic_cast and then catch any std::bad_cast exceptions that are thrown.

Fibbs
  • 1,350
  • 1
  • 13
  • 23
  • But in general, one shouldn't be doing this. (i.e. it's bad design to store pointers-to-base if you actually need to be accessing derived members.) – Oliver Charlesworth Mar 28 '16 at 17:09
  • Sometimes it is unavoidable, though in such situations I'd prefer the base to implement the full interface with virtual methods so that there is no need to dynamic_cast. – Fibbs Mar 28 '16 at 17:12