2010-10-05 10 views
6

El siguiente código explica el problema. Complete en same_sub_class para detectar si los dos punteros a la clase base virtual A son, de hecho, la misma clase concreta de .En C++ compruebe si dos instancias de una clase base son de hecho de la misma subclase

struct A { 
    ... 
}: 

struct B : public A { 
    ... 
}: 

struct C : public A { 
    ... 
} 


bool same_sub_class(A * a1, A * a2){ 
    // Fill this in to return true if a1 and a2 are 
    // of the same concrete class 
} 

EDIT:

Cuando miro a mi solicitud necesito algo ligeramente diferente de la anterior. Necesito poder agrupar instancias por su type_id.

FYI. Tengo un mini sistema simbólico de algerbra, así que para hacer manipulaciones es importante conocer el tipo de clase a veces para clasificar y reorganizar expresiones.

Así que se le da un vector de punteros a la instancia de cómo agruparlos por su type_id. Tendría que poder hash el type_id o generar un entero único para cada clase.

+1

suena como lo que realmente necesita es una int estática en cada clase para ordenar por? –

Respuesta

17

Si puede utilizar RTTI,

typeid(*a1) == typeid(*a2) 

creo que también hay que

#include <typeinfo> 

y debe tener una función virtual en sus clases de manera que existe la viable - un destructor debe haz bien

ACTUALIZACIÓN:

No estoy seguro de entender completamente lo que sus requisitos son para la agrupación, pero se puede tratar (¿Es necesario algún tipo de orden determinista ¿Qué debe suceder con sub-subclases??) utilizando el value volvió del operador typeid a cualquiera:

  • Hash la cadena devuelta desde typeid(*ptr).name()
  • typeid(*a1).before(typeid(*a2)) uso como criterio de ordenación. Sin embargo, esto no tiene ningún determinismo entre ejecuciones.

general al considerar RTTI, es una buena idea para ver si algo de esto se puede lograr un mejor uso de las funciones virtuales bien elaborados (double dispatch, por ejemplo). Realmente no puedo decir si hay una buena alternativa en su caso, ya que no entiendo los detalles.

+1

Debe recordar incluir '' también. –

+0

Pero 'A' tiene que ser polimórfico ¿no? – liaK

+2

@liaK, sí, la clase base debe tener al menos una función virtual. – avakar

6
typeid(*a1) == typeid(*a2) 

Tenga en cuenta la desreferencia, es importante.

+0

Mutuamente, por supuesto. –

2

usted podría hacer su propio tipo Identificador:

struct A{ 
... 
protected: 
enum TypeTag{B_TYPE, C_TYPE}; 
TypeTag typeTag; 
}; 

Y luego en los constructores de subclases:

B::B() 
: typeTag(TypeTag::B_TYPE) 
{ 
... 
} 

C::C() 
: typeTag(TypeTag::C_TYPE) 
{ 
... 
} 
+0

typeTag mejor sea privado. No enum pero variable. –

+0

@Manoj: no estoy de acuerdo. typeTag se inicializa en el constructor de subcajas, por lo que no puede ser miembro privado de la clase base. – Adesit

+0

@Adesit: typeTag debe estar protegido. Pero este mecanismo no es perfecto, porque al agregar un descendiente nuevo necesitamos agregar un nuevo miembro de enum. Saludos a Odessa :) – zabulus

0

Hay una función en C++ llamada RTTI (información de tipo en tiempo de ejecución), que le permite haz tales cosas

Otra posibilidad de tener la verificación del tipo de tiempo de ejecución es crear una clase base de la cual derivan todas sus clases. En su clase base, incluya un campo que contenga su tipo como una cadena o un número.

0

Un truco que puede o no puede trabajar con RTTI, dependiendo de su compilador, es el siguiente

const type_info &a1_type_info= typeid(*a1); 
const type_info &a2_type_info= typeid(*a2); 

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info; 

Si el compilador crea type_info casos por valor, se producirá un error de la primera prueba, pero tener éxito en el segundo prueba. Si el compilador guarda en caché las instancias, la primera prueba tendrá éxito (si es del mismo tipo) y será mucho más rápida, ya que es solo una comparación de puntero. Si su compilador devuelve instancias diferentes porque a1 y a2 provienen de diferentes bibliotecas compartidas, aún debería funcionar.

1

En realidad, hay respuestas bastante simples para esto. Pero implica plantear las preguntas un poco más claras.

(A) Si quiero almacenar objetos typeinfo en un conjunto desordenado, ¿qué debo hacer?

typeinfo admite el método == y el método name(). El nombre se puede usar para generar un hash y == para igualdad

(B) Si quiero almacenar objetos typeinfo en un conjunto ordenado (std :: set) ¿qué debo hacer?

typeinfo admite el método == y before(). Con un poco de ajuste de estos dos métodos, puedo implementar una interfaz para una función de comparación que me da un orden estricto y débil.

Cuestiones relacionadas