Почему мой вектор не распознает мои производные классы?

У меня огромная проблема, намного больше, чем то, что я собираюсь опубликовать, но если кто-то может помочь мне с этим, то отсюда все будет гладко.

Итак, мой вектор указателей ОТКАЗЫВАЕТСЯ распознавать его производные классы. Позволь мне объяснить.

У меня есть класс объектов Player, из которых происходят Warrior и Wizard. В задании мне предлагается сохранить указанные объекты (Воин и Волшебник) в векторе указателей объектов Player. Это то, что у меня есть до сих пор:

vector<Player *> players; 
    cout << "Please enter the number of players" << endl;
    cin >> numOfPlayers;
    total = amountPlaying(numOfPlayers);
for(int i = 0; i < total; i++)
    {
        temp = members();
        if (temp == "Warrior" || temp == "warrior")
            players[i] = new Warrior();
        if (temp == "Wizard" || temp == "wizard")
            players[i] = new Wizard();
        else
        {
            cout << " wrong input, try again " <<endl;
            i--;
        }
        cin >> *players[i];
    }

Функция членов:

string members()
{
    string response;
    cout << "Please select a Warrior or Wizard" << endl;
    cin >> response;
    return response;
}

Я перегрузил Warrior и Wizard, чтобы они принимали ввод через cin, но не через Player (как сказано в задании). Вот как выглядит Воин (Волшебник такой же, но с Волшебником):

istream& operator>>(istream& in, Warrior& warrior)
{
    int base_strength, base_weapon_level, base_weapon_type;

    cout << "Please enter his/her weapon of choice (1 = sword, 2 = axe, 3 = bow, 4 = knife)" << endl;
    in >> base_weapon_type;
    cout << "Please enter his/her weapon level" << endl;
    in >> base_weapon_level;
    cout << "Please enter strength" << endl;
    in >> base_strength;

    warrior.set_power(base_strength);
    warrior.set_weapon_level(base_weapon_level);
    warrior.set_weapon_type(base_weapon_type);
    return in;
}

Теперь проблема в том, что я получаю эту ошибку (в строке с cin >>*players[i]):

ошибка C2679: двоичный '>>': не найден оператор, который принимает правый операнд типа 'Player' (или нет приемлемого преобразования)

Теперь, как мне это исправить? Я чувствую, что он не будет воспринимать его как Воина или Волшебника, он ВСЕГДА будет воспринимать его как Игрока, но я не хочу этого!

P.S. Я знаю, что все это кажется излишним и далеким от оптимизации, но именно так хотел мой профессор. :|

Любая помощь будет оценена по достоинству, так как я застрял на этом НА ЧАСЫ! Спасибо спасибо спасибо!

-Джон


person Apothem    schedule 25.04.2011    source источник
comment
Вы уверены, что ваш профессор не хотел, чтобы вы сделали Player абстрактным классом, а оператора ›› виртуальным?   -  person jabbie    schedule 25.04.2011
comment
Мой профессор сказал, что я могу поставить оператор ›› перегрузки только в Warrior и Wizard. И это не абстрактно, единственная причина, по которой я так говорю, это то, что люди в моем классе не на том уровне, где абстрактные классы были бы чем-то, что она поставила бы в качестве задания.   -  person Apothem    schedule 25.04.2011


Ответы (4)


Вы получаете эту ошибку, потому что, когда вы здесь разыменовываете указатель на Player, вы получаете объект Player, а не Warrior или Wizard:

cin >> *players[i]

И объект Player не имеет operator>>(), как вы сказали.

Возможные решения:
1. используйте dynamic_cast для преобразования Player* в Wizard* или Warrior* во время выполнения. Можно попробовать, но есть более удобные способы. Пример кода:

Wizard *  pwizard = dynamic_cast <Wizard*>(players[i]);
if (pwizard) {
  // work with pwizard
} 
else {
  Warrior * pwarrior = dynamic_cast <Warrior*>(players[i]);
  if (pwarrior) {
    // work with pwarrior
  }
}
person beduin    schedule 25.04.2011
comment
Каким бы неприятным ни было динамическое литье, у меня это сработало. Я ценю вашу помощь и помощь каждого! Я планирую поговорить с профессором о том, почему она не позволяет нам использовать istream в классе Player. Еще раз спасибо, ребята. - person Apothem; 25.04.2011
comment
Ваша operator<< (она должна была быть operator>>, кстати) не может быть функцией-членом и, следовательно, не может быть виртуальной. - person Marcelo Cantos; 25.04.2011
comment
@Marcelo Cantos: Да, моя вина, спасибо. Я отредактировал свой ответ и немного почитал stackoverflow, учитывая эту тему) - person beduin; 25.04.2011
comment
У вас все еще есть operator<< вместо operator>>. - person Marcelo Cantos; 25.04.2011

cin >> *players[i];

Это вызывает проблему. Вы перегрузили operator>> как:

std::istream & operator>>(std::istream & in, Player &player);
person Nawaz    schedule 25.04.2011

Проблема в том, что ваш operator>> на самом деле рассчитывает работать с Воином, а вектор содержит Игроков.

Вы можете работать с производным классом вверх по дереву вывода, но работать вниз — не такая уж хорошая идея. Что вы можете сделать, так это реализовать operator>> для универсального класса Player, а затем работать с ними, как если бы они были классами Wizard или Warrior. В качестве альтернативы внутри вашего оператора>> вы можете вызвать чистую полиморфную функцию, которая реализована в обоих производных классах, и тогда она сделает всю работу за вас.

Надеюсь это поможет

person Ben Stott    schedule 25.04.2011
comment
ОП утверждает, что условия домашнего задания таковы, что ему не разрешено реализовывать operator>> для общего класса Player. - person QuantumMechanic; 25.04.2011
comment
Quantum прав, из-за моих ограничений я мог только надеяться на попытку динамического приведения, как сказал человек ниже меня. - person Apothem; 25.04.2011
comment
Чтобы ответить на его вопрос, выше сказано, почему «векторный класс не распознает [его] производные классы». С точки зрения фактического дизайна, это простое переосмысление его текущего алгоритма, но я понимаю вашу точку зрения. - person Ben Stott; 25.04.2011

Возможно, ваш профессор запретил базовый класс operator>>, потому что он не будет работать. Вы не можете сделать каноническую операцию чтения потока виртуальной, потому что первым параметром является поток, а не базовый класс.

Обычное решение примерно такое:

class Player {
    ...
    virtual std::istream& read(std::istream& is) = 0;
    ...
};

std::istream& operator>>(std::istream& is, Player& p) { return p.read(is); }
person Marcelo Cantos    schedule 25.04.2011