LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Creating a class object inside another class's constuctor (https://www.linuxquestions.org/questions/programming-9/creating-a-class-object-inside-another-classs-constuctor-4175534572/)

retroCheck 02-19-2015 09:47 PM

Creating a class object inside another class's constuctor
 
I have a Hand class and a Player class. I want the player to own the hand so I am thinking I need a prototype in the Player.h and then in my Player.ccp constructor create it. This is not working. I keep getting an "incomplete type" error. Not sure how I should approach this issue. Am I defeating the purpose of OO by trying to do this way? Any help would be great, thanks.

My player class -
Code:

myHand("deck");
My Player header -
Code:

Hand myHand;

NevemTeve 02-19-2015 11:29 PM

I couldn't compile your example program, maybe you left out important parts.

pan64 02-20-2015 01:52 AM

(so would be nice to give more details, probably some sources) Otherwise the problem is in line 34.

a4z 02-20-2015 03:27 AM

the compiler needs to see the whole Hand class where it needs to see it, this is where it needs to know the size,

if your Player.h declares a value object of type Hand, this is the point where the compiler need to know everything about Hand.
so you it seems you need to include Hand.h in Player.h

please have a look at
http://www.linuxquestions.org/questi...gs-4175464257/

NevemTeve 02-20-2015 03:39 AM

Or use pointers:
Code:

/* player.h */

class Hand;

class Player {
    Hand *hand;
}


johnsfine 02-20-2015 06:10 AM

The two choices for dealing with the incomplete type were given by az4 and NevemTeve.

But, seperate from those details, I can't see how your line of code could be correct:
Code:

myHand("deck");
Where is that line of code and does it really end with a ; and if so, how could it be correct?

I would have expected something like:
Code:

Player::Player( ... ) :
  ...
  myHand("deck"),
  ...
{
  ...
}

or (if you take NevemTeve's suggestion):
Code:

Player::Player( ... ) :
  ...
  myHand( new Hand("deck") ),
  ...
{
  ...
}

Most unskilled C++ coders would write something like:

Code:

Player::Player( ... )
{
  ...
  myHand = Hand("deck");
  ...
}

That ends in ; but is not the line you wrote. It is also an inferior constructor style for several reasons.

NevemTeve 02-20-2015 06:18 AM

Off: the last point could be argued http://yosefk.com/c++fqa/ctors.html#fqa-10.6

retroCheck 02-20-2015 06:36 AM

I usually do post code but I was thinking my whole approach was wrong, not the code.

I tried something different this time. Like what a4z mentioned, I tried creating the Hand object within the Player class but now I am getting errors everywhere I use a method from the Hand class. Example - myHand.addCard(myDeck->dealOne());

Nevemteve, to use a pointer as you mentioned wouldn't I need to pass that in through the constructor?

Code:

//Player.cpp

#include <iostream>
#include "Player.h"
#include "Card.h"
#include "Hand.h"
#include "Deck.h"


using namespace std;

Hand myHand(string assocDeck);

Player::Player(Deck *deck){
        //Name will be set after game determine num of players
        _name = "";
        myHand(deck->getName());
        myDeck = deck;
        //No way to bust on first two cards so bust = 0.
        bust = 0;
        //Player will choose to stay
        stay = 0;
}

Player::~Player(){}
       


int Player::hits(){
        //add card and then determine if busted.
        myHand.addCard(myDeck->dealOne());
        if(getHandValue()  > 21){
                bust = 1;
        }       
}

void Player::stays(){
        stay = 1;
}

int Player::getBust(){
        return bust;
}

void Player::resetBust(){
        bust = 0;
}


void Player::printHand(){
        myHand.printHand();
}

void Player::setName(string name){
        //Not allowing more then ten chars for a name
        //Need output to be readable.
        if(name.length() < 11 && name.length() > 0){
                _name = name;
        }else{
                cout << endl << "Name is too long, ten characters is the limit." << endl;
        }

       
}

void Player::clearHand(){
        myHand.clearHand();
}

int Player::getHandValue(){
        myHand.getHandTotal();
        //return  myHand->getHandTotal();
}

string Player::getName(){
        return _name;
}       

int Player::getStays(){
        return stay;
}

Code:

#include <string>
class Deck;
class Hand;

class Player{
        public:
                //Constructor
                Player(Deck *deck);
                //Destructor
                ~Player();
                //Set name of player
                void setName(std::string name);
                //Get name of player
                std::string getName();
                //hit, add one card to hand
                int hits();
                //Decline to add cards
                void stays();
                //Print hand
                void printHand();
                //Get total of card in hand
                int getHandValue();
                //clear hand which free up memory
                void clearHand();
                //Determine if player has busted.
                int getBust();
                //get stay value
                int getStays();
                //Reset bust
                void resetBust();

        private:
               
                std::string _name;//Name
                //Ptr for player's hand

                //Ptr for player's deck
                Deck *myDeck;
               
                int stay;
                int bust;
};


NevemTeve 02-20-2015 07:10 AM

Be a good boy and create a small, complete, minimal example...

retroCheck 02-20-2015 07:24 AM

Be a good boy???

It comes down to just the first 13 lines of code in the player class. I posted all the other code because of recent comments.

NevemTeve 02-20-2015 07:38 AM

All I ask is a complete, minimal example that compiles in itself (or shows the compilation error you want to demonstrate).

a4z 02-20-2015 11:14 AM

Hand myHand is not in the player hpp

#include "Hand.h" needs to go into hpp

you can not call a constructor on myHand when myHand is already initialized

you need to make this in the construction itself
search for class member initialization
it looks like this
Code:

Player::Player(Deck *deck)
:  _name ( "")
, myDeck(deck)
, myHand(deck->getName())
, bust (0)
{

}


SoftSprocket 02-20-2015 11:33 AM

Quote:

Originally Posted by retroCheck (Post 5320513)
I usually do post code but I was thinking my whole approach was wrong, not the code.

I tried something different this time. Like what a4z mentioned, I tried creating the Hand object within the Player class but now I am getting errors everywhere I use a method from the Hand class. Example - myHand.addCard(myDeck->dealOne());

Nevemteve, to use a pointer as you mentioned wouldn't I need to pass that in through the constructor?

Code:

//Player.cpp

#include <iostream>
#include "Player.h"
#include "Card.h"
#include "Hand.h"
#include "Deck.h"


using namespace std;

Hand myHand(string assocDeck);

Player::Player(Deck *deck){
        //Name will be set after game determine num of players
        _name = "";
        myHand(deck->getName());
        myDeck = deck;
        //No way to bust on first two cards so bust = 0.
        bust = 0;
        //Player will choose to stay
        stay = 0;
}

Player::~Player(){}
       


int Player::hits(){
        //add card and then determine if busted.
        myHand.addCard(myDeck->dealOne());
        if(getHandValue()  > 21){
                bust = 1;
        }       
}

void Player::stays(){
        stay = 1;
}

int Player::getBust(){
        return bust;
}

void Player::resetBust(){
        bust = 0;
}


void Player::printHand(){
        myHand.printHand();
}

void Player::setName(string name){
        //Not allowing more then ten chars for a name
        //Need output to be readable.
        if(name.length() < 11 && name.length() > 0){
                _name = name;
        }else{
                cout << endl << "Name is too long, ten characters is the limit." << endl;
        }

       
}

void Player::clearHand(){
        myHand.clearHand();
}

int Player::getHandValue(){
        myHand.getHandTotal();
        //return  myHand->getHandTotal();
}

string Player::getName(){
        return _name;
}       

int Player::getStays(){
        return stay;
}

Code:

#include <string>
class Deck;
class Hand;

class Player{
        public:
                //Constructor
                Player(Deck *deck);
                //Destructor
                ~Player();
                //Set name of player
                void setName(std::string name);
                //Get name of player
                std::string getName();
                //hit, add one card to hand
                int hits();
                //Decline to add cards
                void stays();
                //Print hand
                void printHand();
                //Get total of card in hand
                int getHandValue();
                //clear hand which free up memory
                void clearHand();
                //Determine if player has busted.
                int getBust();
                //get stay value
                int getStays();
                //Reset bust
                void resetBust();

        private:
               
                std::string _name;//Name
                //Ptr for player's hand

                //Ptr for player's deck
                Deck *myDeck;
               
                int stay;
                int bust;
};


You have several illegal constructs.

Here:
Code:

Hand myHand(string assocDeck);
You are constructing an object using a Hand constructor (presumably it exists?) and then, where a parameter list should be, you are trying to declare a string called assocDeck - which won't pass the compiler.

Here:
Code:

Player::Player(Deck *deck){
        //Name will be set after game determine num of players
        _name = "";
        myHand(deck->getName());
        myDeck = deck;

you take an object that you tried to construct, myHand, and calling it like it is a function. The compiler won't like that.

You should be include <string> in your implementation file and you could read up on header guards.

retroCheck 02-21-2015 08:33 AM

a4z - I tried what you suggested but the compiler kept squawking at me for adding Hand header to Player header. I received a error in Class.cpp. I did get it work and while I do no think it is a bad way of doing it I know I easily could be wrong in assuming that. Here is what I did. I added Hand *myHand to top of Player.cpp and in the constructor {...myHand = new Hand(deck->getName());...}

SoftSprocket - those illegal constructs were me frustrated and throwing stuff out there to see if it would stick. I know I know, not the way to go about it.

a4z 02-21-2015 10:09 AM

Quote:

Originally Posted by retroCheck (Post 5321020)
a4z - I tried what you suggested but the compiler kept squawking at me for adding Hand header to Player header.

this makes no sense, there is a problem but very possible not on the location you expect.
what you post is incomplete and not enough to fix the problem,
put the stuff on github or somewhere else if you want to make it easy to help and you are not able to reduce the problem so that what you post is reproducible.


All times are GMT -5. The time now is 02:34 PM.