C ++ как убедиться, что при использовании виртуального наследования он вызывает унаследованную, а не базовую функцию - PullRequest
1 голос
/ 23 марта 2012

Я очень новичок в C ++ и буду очень признателен за любую помощь. У меня есть это задание, которое играет с классами и наследованием. Насколько я понимаю, я могу написать виртуальную функцию в базовом классе, которая переопределяется функциями с тем же именем в унаследованных классах. Когда я вызываю какой-либо из унаследованных классов, это работает просто отлично, но когда я подключаю их к функции, написанной для приема в базовый класс, даже когда получаемые им объекты являются наследниками классов, он вызывает инициализаторы из унаследованного класса, но другие функционирует только из базового класса. Вот сокращенная версия моего кода:

базовый класс:

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

то, что это делает, сводит на нет движение, а не «качает».

Заранее спасибо за любые указатели в правильном направлении. Это меня озадачило.

-Victoria

Ответы [ 3 ]

3 голосов
/ 23 марта 2012

Нельзя использовать динамическое связывание с переданными при копировании параметрами. Вы должны передавать либо ссылки (Player&), либо ссылки на const (Player const&), либо указатели (Player*), либо указатели на const (Player const*).

Пример: если вы создаете экземпляр Avalanche и передаете его чему-то, что получает Player, это происходит:

C ++ видит подпись, которая получает Player, поэтому он создаст локальную копию вашего объекта, используя конструктор копирования по умолчанию с подписью: Player::Player(Player const&). Этот можно вызвать с вашим аргументом Avalanche, так как он наследуется публично от Player. Попробуйте скрыть конструктор копирования Player, чтобы понять, что происходит.

Пожалуйста, не стесняйтесь указывать на вещи, которые были непонятны для вас.

0 голосов
/ 23 марта 2012

Когда вы вызываете Tournament::bout, вы создаете два новых Player объекта из Avalanche объектов, которые вы передаете.

Конструктор Player не знает о части Avalancheобъект, с которого он копирует / перемещает, и поэтому копирует только часть Player.

p1 и p2 являются Player с, поэтому они действуют как Player с, а не Avalanche s.

Если вы не хотите создавать новые Player объекты, передайте аргументы по ссылке:

Player& Tournament::bout (Player& p1, Player& p2)
{
    p1.setMove();
    p2.setMove();
    return p1;
}
0 голосов
/ 23 марта 2012

Вы передаете Player объекты bout, поэтому вы не пользуетесь полиморфизмом.

Вы должны передавать указатели или по ссылке:

Player bout(Player*, Player*);
//or
Player bout(Player&, Player&);

Примечаниечто в вашей версии, если вы передадите Avalanche объекты методу, вы столкнетесь с нарезкой объектов (посмотрите это).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...