Reputation: 47
I'm very new to C++ and would really appreciate any and all help. I have this assignment that plays around with classes and inheritance. My understanding is that I can write a virtual function in the base class that gets overridden by functions of the same name in inherited classes. When I call any of the inherited classes this works just fine, but when I plug them into a function written to take in the base class, even when the objects it receives are from inherited classes, it calls initializers from the inherited class, but other functions only from the base class. Here is a shortened version of my code:
#ifndef PLAYER_CPP
#define PLAYER_CPP
class Player
{
protected:
string playerThrow;
public:
//function that sets player throw
void virtual setMove();
string performMove() {return(playerThrow);}
};
#endif
class Avalanche: virtual public Player
{
public:
Avalanche();
//set specific move for class
void setMove()
{
//always plays rock
playerThrow = "rock";
}
};
//initializer, inherit from player, set new name
Avalanche::Avalanche() : Player()
{
//initialize name string
string newName;
//set name
newName = "Avalanche Player";
//sets name in player class
name = newName;
}
class Tournament
{
public:
Tournament();
Player bout(Player, Player);
Player Tournament::bout (Player p1, Player p2)
{
p1.setMove();
p2.setMove();
return p1;
}
};
what this winds up doing is setting the move to nothing, rather than to "rock".
Thanks in advance for any pointers in the right direction. This one's got me stumped.
-Victoria
Upvotes: 1
Views: 210
Reputation: 34644
You cannot use dynamic binding with copy-passed parameters. You have to pass either references (Player&
) or const references (Player const&
) or pointers (Player*
) or pointers to const (Player const*
).
Example: If you instantiate an Avalanche
and pass it to something that receives a Player
, this happens:
C++ sees the signature that gets a Player
, so it will create a local copy of your object, using the default copy constructor with the signature: Player::Player(Player const&)
. This can be called with your Avalanche
argument since it is inherited publicly from Player
. Try hiding the copy constructor of Player
, to understand what's going on.
Please feel free to point out things that were not intelligible for you.
Upvotes: 3
Reputation: 40633
When you call Tournament::bout
, you construct two new Player
objects from the Avalanche
objects that you pass in.
The Player
constructor does not know about the Avalanche
part of the object that it is copying/moving from, and so only copies the Player
part.
p1
and p2
are Player
s, so they act like Player
s, not Avalanche
s.
If you don't want to construct new Player
objects, then pass the arguments by reference:
Player& Tournament::bout (Player& p1, Player& p2)
{
p1.setMove();
p2.setMove();
return p1;
}
Upvotes: 0
Reputation: 258618
You're passing Player
objects to bout
, so you're not taking advantage of polymorphism.
You should pass pointers or by reference:
Player bout(Player*, Player*);
//or
Player bout(Player&, Player&);
Note that in your version, if you pass Avalanche
objects to the method, you'll run into object slicing (look that up).
Upvotes: 0