2010-10-05 15 views
6

Il codice seguente spiega il problema. Compilare same_sub_class per rilevare se i due puntatori alla classe base virtuale A sono in effetti la stessa classe di calcestruzzo .In C++ verificare se due istanze di una classe base sono effettivamente della stessa sottoclasse

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:

Mentre guardo la mia domanda ho bisogno di qualcosa di leggermente diverso da quanto sopra. Devo essere in grado di raggruppare le istanze in base al loro id_tipo.

FYI. Ho un mini sistema algerbra simbolico, quindi per fare manipolazioni è importante conoscere il tipo di classe a volte per l'ordinamento e la riorganizzazione delle espressioni.

Così dato un vettore di puntatori ad esempio come raggrupparli in base al loro id_tipo. Dovrei essere in grado di eseguire l'hash del tipo id o generare un numero intero univoco per ogni classe.

+1

suona come quello di cui hai veramente bisogno è un int statico su ogni classe da ordinare? –

risposta

17

Se è possibile utilizzare RTTI,

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

penso che è anche necessario

#include <typeinfo> 

e si deve avere una funzione virtuale nelle classi in modo che esista il vtable - un distruttore dovrebbe fare bene

UPDATE:

Io non sono sicuro ho completamente capito cosa siano le vostre esigenze per il raggruppamento, ma si potrebbe provare (Avete bisogno di un qualche tipo di ordine deterministico Che cosa dovrebbe accadere con sotto-sottoclassi??) utilizzando il value restituito dall'operatore typeid a uno:

  • Hash la stringa restituita da typeid(*ptr).name()
  • Uso typeid(*a1).before(typeid(*a2)) come criterio d'ordine. Questo non ha alcun determinismo tra le corse, però.

Generalmente quando studia RTTI, è una buona idea per vedere se tutto questo può essere realizzato meglio utilizzando funzioni virtuali ottima fattura (double dispatch, per esempio). Non posso davvero dire se nel tuo caso ci sia una buona alternativa, dal momento che non capisco le specifiche.

+1

È necessario ricordare di includere ''. –

+0

Ma 'A' deve essere polimorfico non è ?? – liaK

+2

@liaK, sì, la classe base deve avere almeno una funzione virtuale. – avakar

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

Nota il dereferenziamento, è importante.

+0

Mutualmente, ovviamente. –

2

si potrebbe rendere il proprio tipo Identifier:

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

E poi nei costruttori di sottoclassi:

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

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

typeTag meglio essere privato. Non enum ma variabile. –

+0

@Manoj: non sono d'accordo. typeTag è inizializzato nel costruttore sublasses, quindi non può essere membro privato della classe base. – Adesit

+0

@Adesit: typeTag deve essere protetto. Ma questo meccanismo non è perfetto, perché aggiungendo un nuovo discendente abbiamo bisogno di aggiungere un nuovo membro di enum. Cordiali saluti a Odessa :) – zabulus

0

C'è una funzione in C++ chiamato RTTI (rtti), che consente di fai queste cose

Un'altra possibilità per il controllo del tipo di runtime consiste nel creare una classe base da cui derivano tutte le classi. Nella tua classe base includi un campo che contiene il suo tipo come una stringa o un numero.

0

Un trucco che può o non può funzionare con RTTI, a seconda del compilatore, è la seguente

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; 

Se il compilatore crea type_info istanze di valore, questo fallirà il primo test, ma avere successo al secondo test. Se il compilatore memorizza nella cache le istanze, il primo test avrà esito positivo (se è lo stesso tipo) e sarà molto più veloce poiché è solo un confronto tra puntatori. Se il compilatore restituisce istanze diverse perché a1 e a2 provengono da diverse librerie condivise, dovrebbe comunque funzionare.

1

In realtà ci sono risposte abbastanza semplici a questo. Ma implica porre le domande un po 'più chiare.

(A) Se desidero memorizzare gli oggetti tipoinfo in un file non ordinato, cosa devo fare?

typeinfo supporta il metodo == e il metodo name(). Il nome può essere utilizzato per generare un hash e == per l'uguaglianza

(B) Se voglio memorizzare oggetti di tipoinfo in un set_ordinato (std :: set) cosa devo fare?

typeinfo supporta il metodo == e il metodo before(). Con un po 'di involucro di questi due metodi posso implementare un'interfaccia per una funzione di confronto che mi dà un rigoroso ordine debole.

Problemi correlati