2009-12-31 14 views
5

Jeśli dobrze rozumiem, typeid może określić rzeczywisty typ polimorfizmu, natomiast typeof nie.Uzyskaj typ zmiennej

Czy to prawda, że ​​ich zwroty są wykorzystywane do różnych celów: zwrot typeof jest używany jako słowo kluczowe typu, które może definiować zmienną, ale zwrot typeid nie może?

Czy istnieje sposób na uzyskanie rzeczywistego typu dla polimorfizmu i użycie zwrotu jako słowa kluczowego typu do zdefiniowania innej zmiennej? Mam nadzieję uzyskać typ klasy pochodnej od wskaźnika wskazującego na klasę podstawową i zdefiniować zmienną lub wskaźnik do klasy pochodnej. Coś jak:

baseclass *p = new derivedclass 
typexxx(*p) *pp = dynamic_cast<typexxx(*p) *> (p); 
// would like to convert the pointer from pointing to a base class 
// to its derived class 

Dziękuję bardzo!

+6

Czy możesz podać przykład DLACZEGO chcesz to zrobić? Głównym punktem hierarchii dziedziczenia jest to, że zwykle nie musisz znać faktycznego typu. –

+0

Po prostu chcesz odwołać się do niektórych elementów zdefiniowanych w klasie pochodnej, ale nie w klasie bazowej. Nie jestem pewien, czy dobrze jest dodać funkcje członkowskie do klasy bazowej o tej samej nazwie co klasy pochodne i zadeklarować je jako wirtualne, ponieważ te funkcje składowe są zbyt specyficzne dla tej konkretnej klasy pochodnej i nie są wymagane w innych pochodne klasy, a funkcja podstawowa będzie większa, jeśli dodaję do niej. – Tim

+1

OK, możesz robić, co chcesz z dynamic_cast, ale będziesz musiał użyć drabiny if, aby utworzyć wskaźniki pochodne. –

Odpowiedz

7

c++0x będzie miał decltype które mogą być używane tak:

int someInt; 
decltype(someInt) otherIntegerVariable = 5; 

ale dla zwykłego starych C++, niestety, nie.

Przypuszczam, że decltype tak naprawdę nie będzie zbyt pomocne, ponieważ chcesz typ polimorficzny, nie zadeklarowanego typu. Najprostszym sposobem zrobienia tego, co chcesz, jest próba dynamicznego rzutowania na określony typ i sprawdzenie pod kątem NULL.

struct A { 
    virtual ~A() {} 
}; 
struct B : public A {}; 
struct C : public A {}; 

int main() { 
    A* x = new C; 
    if(B* b_ptr = dynamic_cast<B*>(x)) { 
     // it's a B 
    } else if(C* c_ptr = dynamic_cast<C*>(x)) { 
     // it's a C 
    } 
} 
+0

Dzięki Evan! Ale czasami muszę określić typ w czasie wykonywania, na przykład za pomocą argumentu wiersza poleceń. Zobacz mój post tutaj http://stackoverflow.com/questions/1984492/runtime-determine-type-for-c, zrozumiesz. – Tim

+0

'if (B * b_ptr = dynamic_cast (x))' i nie ma potrzeby dla zmiennych ani błędnych zakresów. Dodatkowo możesz napisać bardziej naturalną 'else if' zamiast' else {... if ...} ' –

+0

@Roger: uczysz się czegoś nowego każdego dnia, nie wiedziałem, że możesz zadeklarować zmienną wewnątrz instrukcji if. i dają odpowiedni zakres. Zaktualizuję moją odpowiedź. –

3

Zakładając hierarchii < A - B - c <

A * p = new AorBorC; // create new object of some sort 

if (dynamic_cast <C*>(p)) { 
    C * c = dynamic_cast <C*>(p); 
    c->CFunc(); 
} 
else if (dynamic_cast <B*>(p)) { 
    B * b = dynamic_cast <B*>(p); 
    b->BFunc(); 
} 
else if (dynamic_cast <A*>(p)) { 
    A * a = dynamic_cast <A*>(p); 
    a->AFunc(); 
} 

przypadku AFunc, BFunc, CFunc są specyficzne dla poszczególnych klas, a nie wirtualny. Oczywiście można to zoptymalizować nieco.

+0

'if (C * c = dynamic_cast (p)) {/ * użyj c * /}' Nie trzeba rzucać dwa razy. –

+1

Całkiem - starałem się uczynić rzeczy bardziej przejrzystymi przez bycie zdyszanym. –