2011-01-31 3 views
3

Это строго в С.вниз Кастинг иерархии с неполиморфной Типы

Допустим, вы дали одну базовую-структуру, а также 2 других производных структур. Эти производные структуры не производятся в классическом смысле (то есть: A: B), а скорее содержат только структуры базового типа. Так что, если структура А основание и B является одним из 2-х производных структур, B будет иметь элемент типа А. Как это:

struct A { 
    // blah blah... 
}; 

struct B { 
    A part_a; 
    // more stuff... 
} 

struct C { 
    A part_a; 
    // SO MUCH STUFF 
} 

у вас есть функция, A_downcast_B, что-то вроде этого:

B * A_downcast_B(A * a) 
{ 
    // downcast the A* here somehow 
} 

Вы хотите эту функцию, чтобы вернуть 0 или -1 если 'a' не может быть успешно downcasted на структуру типа B. Так, например, если «производная» структура типа C имела указатель на нее типа A*, и этот указатель был передан этой функции, функция вернет 0, -1 или null.

Есть ли способ сделать это? Я думал об этом в течение нескольких часов, и это заставило меня задохнуться.

ответ

8

Это невозможно сделать, не встраивая какую-либо информацию типа времени выполнения в struct A. Например, вы можете сохранить указатель на некоторую информацию о типе, и вы должны инициализировать это в любое время, когда вы создаете любую «производную» структуру.

struct RTTI { 
    const char *typename; 
    // etc. 
}; 

struct A { 
    const RTTI *rtti; 
    // rest of A 
}; 

struct B { 
    A part_a; 
    ... 
}; 

const RTTI RTTI_B = {"B"}; 

struct C { 
    A part_a; 
    ... 
}; 

const RTTI RTTI_C = {"C"}; 

void make_B(B *b) 
{ 
    b->part_a.rtti = &RTTI_B; 
    // make the rest of B 
} 

void make_C(C *c) 
{ 
    c->part_a.rtti = &RTTI_C; 
    // make the rest of C 
} 

B * A_downcast_B(A * a) 
{ 
    return (a->rtti == &RTTI_B) ? (B*)a : NULL; 
} 

Обратите внимание, что это на самом деле просто упрощенная реализация С ++ dynamic_cast оператора, который работает только с полиморфными типами данных. Причина этого в том, что среда выполнения может получить доступ только к информации типа времени выполнения, если объект имеет встроенную в него информацию типа - ее vtable.

+1

OHHH, ЧТО ТАКОЕ RTTI. Черт бы побрал мою лень за то, что я не позвонил мне. Большое спасибо! :) –