2010-10-05 15 views
6

Poniższy kod wyjaśnia problem. Wypełnij ten sam_sub_class, aby wykryć, czy dwa wskaźniki do wirtualnej klasy bazowej A są w rzeczywistości tą samą konkretną klasą .W języku C++ sprawdź, czy dwie instancje klasy bazowej znajdują się w tej samej podklasie.

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:

Jak patrzę na mojego wniosku muszę coś nieco inny od powyższego. Muszę być w stanie grupować instancje według ich id_typu.

FYI. Mam mini symboliczny system algerbry, więc aby robić manipulacje ważne jest, aby znać typ klasy czasami do sortowania i przestawiania wyrażeń.

Tak dany wektor wskaźników do przykładu, jak pogrupować je według ich id_wp. Będę musiał albo móc mieszać typ_id lub generować unikalną liczbę całkowitą dla każdej klasy.

+1

brzmi jak to, czego naprawdę potrzebujesz, to statyczna int dla każdej klasy, według której chcesz sortować? –

Odpowiedz

17

Jeśli można użyć RTTI,

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

Chyba trzeba także

#include <typeinfo> 

I trzeba mieć funkcję wirtualną w swoich klasach, tak aby vtable istnieje - destruktor powinien dobrze.

UPDATE:

Nie jestem pewien, czy w pełni zrozumieć, co się wymagania są do grupowania, ale można spróbować (Czy trzeba jakiś deterministyczny zamawiania Co powinno się zdarzyć z podklasy?) używając value wrócił z operatorem typeid albo:

  • Hash ciąg zwrócony z typeid(*ptr).name()
  • Zastosowanie typeid(*a1).before(typeid(*a2)) jako kryterium zamawiania. Nie ma to jednak żadnego determinizmu między biegami.

Ogólnie biorąc biorąc pod uwagę RTTI, dobrze jest sprawdzić, czy którekolwiek z nich można osiągnąć lepiej przy użyciu dobrze spreparowanych funkcji wirtualnych (na przykład double dispatch). Naprawdę nie mogę powiedzieć, czy istnieje dobra alternatywa w twoim przypadku, ponieważ nie rozumiem szczegółów.

+1

Należy również pamiętać o włączeniu ''. –

+0

Ale 'A' musi być polimorficzny, czyż nie? – liaK

+2

@liaK, tak, klasa podstawowa musi mieć co najmniej jedną funkcję wirtualną. – avakar

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

Uwaga na dereferencję, jest to ważne.

+0

Wzajemnie, oczywiście. –

2

Można zrobić własny typ identyfikatora:

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

a potem w konstruktorów podklasy:

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

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

typeTag lepiej być prywatne. Nie wyliczać, ale zmienne. –

+0

@Manoj: nie zgadzam się. typeTag jest inicjowany w konstruktorze sublasses, więc nie może być prywatnym członkiem klasy bazowej. – Adesit

+0

@Adesit: typTag musi być chroniony. Ale ten mechanizm nie jest idealny, ponieważ po dodaniu nowego potomka musimy dodać nowego członka enum. Pozdrawiamy Odessa :) – zabulus

0

Jest to funkcja w C++ nazywa RTTI (rtti), który pozwala na rób takie rzeczy.

Inną możliwością sprawdzenia typu środowiska wykonawczego jest utworzenie klasy bazowej, z której pochodzą wszystkie klasy. W swojej klasie bazowej uwzględnij pole, które zawiera jego typ jako ciąg lub liczbę.

0

jeden trik, który może lub nie może pracować z RTTI, w zależności od kompilatora, jest następujący

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; 

Jeśli kompilator tworzy type_info instancji przez wartość, to nie pierwszy test, ale sukces na sekundę test. Jeśli Twój kompilator buforuje instancje, pierwszy test się powiedzie (jeśli jest tego samego typu) i będzie znacznie szybszy, ponieważ jest to tylko porównanie wskaźnika. Jeśli Twój kompilator zwraca różne instancje, ponieważ a1 i a2 pochodzą z różnych bibliotek współdzielonych, to nadal powinno działać.

1

W rzeczywistości istnieje dość prosta odpowiedź na to pytanie. Ale wiąże się to z postawieniem pytań nieco jaśniej.

(A) Jeśli chcę przechowywać obiekty typuinfo w unordered_set, co muszę zrobić?

typeinfo obsługuje metodę == i name(). Nazwa może być używana do generowania skrótu i ​​== dla równości

(B) Jeśli chcę przechowywać obiekty typuinfo w uporządkowanym zestawie (std :: set), co muszę zrobić?

typeinfo obsługuje metodę == i before(). Przy odrobinie owijania tych dwóch metod mogę zaimplementować interfejs dla funkcji Porównaj, która daje mi ścisłą słabą kolejność.

Powiązane problemy