quipish
quipish

Reputation: 47

C++ how to ensure when using virtual inheritance that it calls the inherited and not the base function

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:

base class:

#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

inherited class:

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;
}

How I'm trying to use it:

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

Answers (3)

bitmask
bitmask

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

Mankarse
Mankarse

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 Players, so they act like Players, not Avalanches.

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

Luchian Grigore
Luchian Grigore

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

Related Questions