Pregunta

Supongamos que tengo una clase Base y varias clases Derivadas . ¿Hay alguna forma de lanzar un objeto a una de las clases derivadas sin la necesidad de escribir algo como esto:


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 {
  ...
}
¿Fue útil?

Solución

No.

Lee sobre el polimorfismo. Casi todos los " reparto dinámico " La situación es un ejemplo de polimorfismo que lucha por ser implementado.

Cualquier decisión que esté tomando en el reparto dinámico ya se ha tomado. Solo delegue el trabajo real a las subclases.

Has omitido la parte más importante de tu ejemplo. El trabajo útil, polimórfico.

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 cada subclase implementa doSomethingUseful, todo esto es mucho más simple. Y polimórfico.

object->doSomethingUseful();

Otros consejos

Puedes usar dynamic_cast y hacer una prueba de NULL, pero lo recomiendo con fuerza en lugar de eso, considerar refactorizar el código.

Si necesita un manejo específico de subclase, Método de plantilla puede ser útil, pero sin saberlo Lo que estás tratando de lograr, es solo una vaga suposición.

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

Tengo los siguientes métodos en mi tipo de puntero inteligente, simulando C # 'is' y 'as':

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);}

Puedes hacer esto usando dynamic_cast , por ejemplo:

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.
}

Pero como han dicho otros, un código como este puede indicar un mal diseño, y generalmente debe usar funciones virtuales para implementar el comportamiento polimórfico.

por lo general, este es un signo de un mal diseño. ¿Por qué necesitas hacer esto? Es posible que se pueda rediseñar para que esto no sea necesario.

¿Qué estás tratando de lograr, exactamente? En mi experiencia, cosas como estas son una señal de mal diseño. Vuelva a evaluar su jerarquía de clases, porque el objetivo del diseño orientado a objetos es hacer que cosas como estas sean innecesarias.

Su ejemplo no se transferirá, porque no se especifica el formato exacto del nombre (). Puedes probar una sucesión de dynamic_cast s. Dynamic_cast devuelve un puntero nulo si realiza la conversión al tipo incorrecto. Sin embargo, si estás haciendo un tipo de conmutador como este, hay algún problema con tu diseño.

Creo que dynamic_cast es el camino a seguir, pero no creo que este sea un mal diseño para todas las condiciones posibles porque el objeto a ser fundido puede ser algo provisto por algún módulo de terceros. Digamos que el objeto fue creado por un complemento del cual el autor de la aplicación no tiene conocimiento. Y ese complemento en particular puede crear el tipo de objeto Derived1 (siendo la versión anterior) o el tipo de objeto Derived2 (ser la nueva versión). Tal vez la interfaz de plug-in no fue diseñada para hacer cosas específicas de la versión, simplemente crea el objeto, por lo que la aplicación debe hacer este tipo de comprobación para garantizar la conversión / ejecución adecuada. Después de esto, podemos llamar de forma segura object.doSomethingUsefulThatDoesNotExistInDerived1 ();

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top