Question

Supposons que j'ai une classe Base et plusieurs classes Dérivée . Existe-t-il un moyen de convertir un objet dans l'une des classes dérivées sans avoir à écrire quelque chose comme ceci:


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
}
...
else {
  ...
}
Était-ce utile?

La solution

Ne pas.

Lisez sur le polymorphisme. Presque tous les " castes dynamiques " La situation est un exemple de polymorphisme qui a du mal à être mis en œuvre.

Quelle que soit la décision que vous prenez dans la distribution dynamique a déjà été prise. Il suffit de déléguer le travail réel aux sous-classes.

Vous avez omis la partie la plus importante de votre exemple. Le travail utile et polymorphe.

string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
   d1->doSomethingUseful();
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
   d2->doSomethingUseful();
}
...
else {
  ...
}

Si chaque sous-classe implémente doSomethingUseful, tout cela est beaucoup plus simple. Et polymorphe.

object->doSomethingUseful();

Autres conseils

Vous pouvez utiliser dynamic_cast et tester NULL, mais fortement , vous envisageriez de refactoriser le code à la place.

Si vous avez besoin d'une gestion spécifique à une sous-classe, la méthode du modèle peut être utile, mais sans le savoir. ce que vous essayez de réaliser, ce n’est qu’une vague conjecture.

Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

J'ai les méthodes suivantes sur mon type de smartpointer, simulant le C # 'est' et 'en tant que':

template< class Y > bool is() const throw()
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
template< class Y > Y* as() const throw()
    {return null() ? NULL : dynamic_cast< Y* >(ptr);}

Vous pouvez le faire en utilisant dynamic_cast , par exemple:

if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
    // object points to a Derived1
    d1->foo();
}
else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
    // object points to a Derived2
    d2->bar();
}
else {
    // etc.
}

Mais comme d’autres l’ont déjà dit, un code tel que celui-ci peut indiquer une mauvaise conception et vous devez généralement utiliser fonctions virtuelles pour implémenter un comportement polymorphe.

Habituellement, c’est le signe d’une mauvaise conception. Pourquoi avez-vous besoin de faire cela? Il serait peut-être possible de revoir la conception de sorte que cela ne soit pas nécessaire.

Qu'est-ce que vous essayez d'accomplir, exactement? D'après mon expérience, de telles choses sont un signe de mauvaise conception. Réévaluez votre hiérarchie de classes, car l'objectif de la conception orientée objet est de rendre inutiles des choses comme celle-ci.

Votre exemple ne portera pas, car le format exact de name () n'est pas spécifié. Vous pouvez essayer une succession de dynamic_cast s. Dynamic_cast renvoie un pointeur null si vous transtypez vers un type incorrect. Cependant, si vous utilisez un commutateur de type comme celui-ci, il y a quelque chose qui cloche dans votre conception.

Je pense que dynamic_cast est la voie à suivre, mais je ne pense pas particulièrement que ce soit une mauvaise conception pour toutes les conditions possibles car un objet à diffuser peut être fourni par un module tiers. Supposons que l'objet a été créé par un plug-in dont l'auteur de l'application n'a aucune connaissance. Et ce plug-in particulier peut créer un objet de type Derived1 (ancienne version) ou un objet de type Derived2 (étant la nouvelle version). Peut-être que l'interface de plug-in n'a pas été conçue pour effectuer des tâches spécifiques à une version, elle crée simplement l'objet, de sorte que l'application doit effectuer ce type de vérification pour garantir une conversion / exécution correcte. Après cela, nous pouvons appeler en toute sécurité object.doSomethingUsefulThatDoesNotExistInDerived1 ();

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top