La compréhension de la double répartition C++
J'essaie de comprendre comment la double répartition des œuvres. J'ai créé un exemple où un monstre guerrier et un dérivé de la classe abstraite Créature pouvait se battre. La classe Créature a la méthode de la "lutte", qui est définie dans les classes dérivées, et dans chaque classe dérivée est définie ce qui se passe si guerrier se bat avec guerrier ou avec le monstre etc. J'ai écrit le code suivant:
#include<iostream>
using namespace std;
class Monster;
class Warrior;
class Creature{
public:
virtual void fight(Creature&) =0;
};
class Monster: public Creature{
void fightwho(Warrior& w) {cout<<"Monster versus Warrior"<<endl; }
void fightwho(Monster& m) {cout<<"Monster versus Monster"<<endl; }
public:
void fight(Creature& c) {c.fightwho(*this);}
};
class Warrior: public Creature{
void fightwho(Warrior& w) {cout<<"Warrior versus Warrior"<<endl; }
void fightwho(Monster& m) {cout<<"Monster versus Warrior"<<endl; }
public:
void fight(Creature& c) {c.fightwho(*this);}
};
int main()
{
Warrior w;
Monster m;
w.fight(m);
}
Cette résultats dans d'erreur du compilateur, que je prévois:
ex12_10.cpp: En fonction de membre de ‘virtual void Monstre::lutte(Créature&)’: ex12_10.rpc:17:30: erreur: classe de Créature " n'a pas de membre nommé ‘fightwho’
ex12_10.cpp: En fonction de membre de ‘virtual void Guerrier::lutte(Créature&)’: ex12_10.rpc:24:29: erreur: classe de Créature " n'a pas de membre nommé ‘fightwho’
Mais je ne sais pas comment procéder à partir d'ici... s'il vous Plaît aider.
OriginalL'auteur gartenzwerg | 2012-09-25
Vous devez vous connecter pour publier un commentaire.
Bien, évidemment, vous n'avez pas vraiment
fightwho
déclaré dans votreCreature
classe, de sorte que vous besoin de le déclarer il y a, et il déclare quevirtual
.Double expédition travaille dans une manière que pour l'appel (ce qui suppose
Warrior& w = ...
, pasWarrior w
):D'abord le virtuel, le mécanisme choisi
Warrior::fight
au lieu deMonster::fight
et puis, la surcharge, le mécanisme de sélectionMonster::fightwho(Warrior& m)
au lieu deWarrior::fightwho(Warrior& m)
. Notez que cela aurait plus de sens si vous avez:Par conséquent, la méthode qui sera finalement appelé sera distribué en fonction du type de l'objet sur lequel vous l'appelez et le type de l'objet envoyé en argument, c'est à dire double expédition
En outre, veuillez noter que cela pourrait ne pas être le meilleur exemple que vos types sont membres de la même hiérarchie. Visiteur modèle de conception est un bon exemple de la double répartition des implémentations dans des langues qui ne prennent pas en charge, comme des citoyens à part entière (c'est à dire C++ et dérivés: Java, C#...)
@CrazyCasta correctement des notes, lors de votre hiérarchie de classe commence à se développer, cette approche devient beaucoup plus difficile à entretenir et peuvent provoquer une explosion du nombre de méthodes, afin de choisir avec soin...
Creature::Creature()': ex12_10.cpp:(.text._ZN8CreatureC2Ev[_ZN8CreatureC5Ev]+0xf): undefined reference to
vtable pour la Créature' /tmp/cceFWViM.o:(.rodata._ZTV7Warrior[vtable pour le Guerrier]+0x18): undefined reference toCreature::fightwho(Creature&)' /tmp/cceFWViM.o:(.rodata._ZTV7Monster[vtable for Monster]+0x18): undefined reference to
Créature::fightwho(Créature&)' /tmp/cceFWViM.o:(.rodata._ZTI7Warrior[typeinfo pour le Guerrier]+0x10): undefined reference to `typeinfo pour Êtrevous avez besoin de la déclarer comme virtuelle pure ou de fournir le corps.
il fonctionne si j'ajoute à la Créature "virtual void fightwho(Guerrier&)=0; virtual void fightwho(Monster&)=0;". Mais Est-il possible de mettre en œuvre sans nommer le Monstre et le Guerrier dans la Créature? Si j'ajoute "virtual void fightwho(Créature&)=0;" il ne fonctionne pas
Non, il n'est pas possible, vous avez besoin fightwho(Guerrier&) et fightwho(Monster&) dans la Créature, donc pourquoi cela peut devenir très méchant, très rapidement.
vous avez raison, bien sûr. J'ai remarqué manquant
=0
et ignoré l'argument de l'complètementOriginalL'auteur Zdeslav Vojkovic
Ma contribution aux réponses ci-dessus est de fournir le bien-testé exemple pour clarifier la double répartition concept dans la réalité. Si vous examinez le code ci-dessous, vous trouverez la réponse de comment puis-je mettre en œuvre par moi-même.
OriginalL'auteur Validus Oculus
Si vous voulez faire cela, vous aurez besoin d'utiliser RTTI. Vous aurez besoin de vérifier le type de la chose est passée. En général, ce n'est pas le meilleur modèle de conception à utiliser si vous pouvez l'éviter. Si vous souhaitez interagir deux objets en général, vous voulez utiliser l'interface standard de l'autre. Par exemple, vous pourriez dire créature.attaque(other_creature) et attaque pourrait requête de la défense de la créature, et en fonction de ça et c'est propre statistiques de publier une mise à jour hp pour la other_creature.
Votre méthode nécessite une fonction abstraite dans la classe de base pour chaque type de classe que vous souhaitez interagir avec (le plus souvent, chaque type qui dérive de la classe de base). Qui devient très laid, très rapidement.
Je suis complètement d'accord - et c'est pourquoi je ne suis pas particulièrement friand des habitudes des Visiteurs, en particulier lors de la hiérarchie commence à grandir, il se transforme rapidement en un gâchis.
J'ai édité ma réponse à souligner le point que vous avez soulevé.
Je ne suis pas au courant des meilleures options pour le double envoi en C++ (et dérivés de langues), vous devez fournir toutes les combinaisons explicitement.
OriginalL'auteur CrazyCasta