Usando uma função praticamente herdou não virtualmente?
-
05-07-2019 - |
Pergunta
Eu tenho que correr em apuros tentando implementar funcionalidade para serialização de algumas classes no meu jogo. Eu armazenar alguns dados em um arquivo de texto simples e eu quero ser capaz de salvar e carregar de / para ele. Os detalhes deste, no entanto, são irrelevantes. O problema é que eu estou tentando fazer com que cada objeto que é interessante para o salvar o arquivo para ser capaz de serializar si. Por isso eu tenha definido uma interface ISerializable, com declarações puramente virtuais do operador << e operador >>.
A classe de hierarquia é algo como isto
-> GameObject -> Character -> Player ...
ISerializable -> Item -> Container ...
-> Room ...
Isto significa que há muitas situações possíveis para a serialização de objetos de diferentes classes. Recipientes, por exemplo, deve chamar operador << em todos os itens contidos.
Agora, desde que operator >> é virtual, eu pensei que se eu queria serialize algo que implementa a funcionalidade definida na ISerializable eu poderia apenas fazer algo como
ostream & Player::operator<<(ostream & os){
Character::operator<<(os);
os << player_specific_property 1 << " "
<< player_specific_property 2 << "...";
return os;
}
e
ostream & Character::operator<<(ostream & os){
GameObject::operator<<(os);
os << character_specific_property 1 << " "
<< character_specific_property 2 << "...";
return os;
}
mas eu aprendi rapidamente que esta primeira tentativa foi ilegal. O que eu estou pedindo aqui é como faço para contornar este ?
Eu não me sinto como a implementação de uma função manualmente para cada classe. Eu acho que eu estou procurando algo como a funcionalidade super
de Java.
Qualquer ajuda é apreciada.
- COMENTÁRIO DO EDIT ------------
Tudo bem, última vez que eu estava com pressa quando eu estava escrevendo a questão. O código agora é mais como era quando eu tentei para compilá-lo. Fixei a questão eo problema que tive não estava relacionado com a pergunta. Tenho vergonha de dizer que foi causado por um erro na esteira de uma grande refatoração do código, eo fato de que o operador não foi implementado em todas as classes base.
Muitos agradecimentos para as respostas no entanto!
Solução
O problema não está na sua tentativa de chamar uma função virtual não virtualmente. O problema é esta linha: os = Character::operator<<(os);
. Essa é uma atribuição, mas std::ostream
não tem um operator=
.
Você não precisa a atribuição de qualquer maneira. O fluxo retornado é o mesmo fluxo como o fluxo de você passar. A única razão pela qual ele é retornado é assim que você pode encadear-los.
Assim, a correção é apenas para alterar o código para
ostream & Player::operator<<(ostream & os){
Character::operator<<(os);
os << player_specific_property 1 << " "
<< player_specific_property 2 << "...";
return os;
}
Outras dicas
Isto não é como a sobrecarga de operador << para obras ostream. O operador da mão esquerda é um ostream (daí você tem que sobrecarregá-lo como uma função gratuita) e o operador do lado direito é o seu objeto (que é por isso que o mecanismo virtual não seria facilmente trabalho.
Eu suponho que você poderia tentar:
class Base
{
//...
virtual std::ostream& output(std::ostream&) const;
};
std::ostream& operator<< (std::ostream& os, const Base& obj)
{
return obj.output(os);
}
Agora uma classe derivada naturalmente pode chamar o método de seu pai (s) de saída:
class Derived: public Base
//...
virtual std::ostream& output(std::ostream& os) const
{
Base::output(os);
return os << my_specific_data;
}
};