Использование виртуально унаследованной функции не виртуально? - PullRequest
2 голосов
/ 26 ноября 2009

Я столкнулся с проблемой, пытаясь реализовать функциональность для сериализации некоторых классов в моей игре. Я храню некоторые данные в необработанном текстовом файле и хочу иметь возможность сохранять и загружать в него / из него. Детали этого, однако, не имеют значения. Проблема в том, что я пытаюсь сделать так, чтобы каждый интересующий объект сохранения мог сериализоваться сам. Для этого я определил интерфейс ISerializable с чисто виртуальными объявлениями оператора << и оператора >>.

Класс Иерархия выглядит примерно так

              -> GameObject -> Character -> Player ...
ISerializable               -> Item -> Container ...
              -> Room ...

Это означает, что существует множество возможных ситуаций для сериализации объектов различных классов. Например, контейнеры должны вызывать оператор << для всех содержащихся элементов. </p>

Теперь, поскольку operator >> является виртуальным, я подумал, что если я хочу сериализовать что-то, реализующее функциональность, определенную в ISerializable, я мог бы просто сделать что-то вроде

ostream & Player::operator<<(ostream & os){
    Character::operator<<(os);
    os << player_specific_property 1 << " " 
       << player_specific_property 2 << "...";
    return os;
}

, а затем

ostream & Character::operator<<(ostream & os){
    GameObject::operator<<(os);
    os << character_specific_property 1 << " " 
       << character_specific_property 2 << "...";
    return os;
}

но я быстро узнал, что эта первая попытка была незаконной. То, что я спрашиваю здесь, это как мне обойти это ?

Мне не хочется реализовывать функцию вручную для каждого класса. Наверное, я ищу что-то вроде super функциональности из Java.

Любая помощь приветствуется.

- КОММЕНТАРИИ О РЕДАКТИРОВАНИИ ------------

Хорошо, в прошлый раз я спешил, когда писал вопрос. Код теперь больше похож на код, когда я пытался его скомпилировать. Я исправил вопрос, и проблема, с которой я столкнулся, не была связана с заданным вопросом. Мне стыдно говорить, что это было вызвано ошибкой в ​​результате большого рефакторинга кода и тем фактом, что оператор был реализован не в каждом базовом классе.

Большое спасибо за ответы, однако!

Ответы [ 2 ]

4 голосов
/ 26 ноября 2009

Проблема не в вашей попытке вызвать виртуальную функцию не виртуально. Проблема в этой строке: os = Character::operator<<(os);. Это назначение, но std::ostream не имеет operator=.

Вам все равно не нужно задание. Возвращенный поток - это тот же поток, что и поток, который вы передаете. Единственная причина, по которой он возвращается, - это возможность связать их.

Следовательно, исправление состоит в том, чтобы просто изменить код на

ostream & Player::operator<<(ostream & os){
    Character::operator<<(os);
    os << player_specific_property 1 << " " 
       << player_specific_property 2 << "...";
    return os;
}
3 голосов
/ 26 ноября 2009

Это не то, как оператор перегрузки << для ostream работает. Левый оператор - это ostream (следовательно, вы должны перегрузить его как свободную функцию), а правый оператор - ваш объект (вот почему виртуальный механизм не может легко работать. </p>

Полагаю, вы могли бы попробовать:

class Base
{
    //...
    virtual std::ostream& output(std::ostream&) const;
};

std::ostream& operator<< (std::ostream& os, const Base& obj)
{
    return obj.output(os);
}

Теперь производный класс может естественным образом вызывать метод вывода своих родителей:

class Derived: public Base
    //...
    virtual std::ostream& output(std::ostream& os) const
    {
        Base::output(os);
        return os << my_specific_data;
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...