Show Lecture.Reflection as a slide show.
CS253 Reflection
typeid
int alpha;
short beta;
const type_info &ta = typeid(alpha), &tb = typeid(beta);
cout << "type of alpha: " << ta.name() << '\n'
<< "type of beta: " << tb.name() << '\n'
<< "Equal? " << boolalpha << (ta==tb) << '\n';
type of alpha: i
type of beta: s
Equal? false
Easier
One rarely actually instantiates a variable of class
type_info
:
float gamma;
cout << "type of gamma: " << typeid(gamma).name();
type of gamma: f
You can also pass a type as an argument to typeid()
.
cout << "type of double: " << typeid(double).name();
type of double: d
Built-in Types
Every type has a corresponding implementation-defined encoding:
cout << typeid(char ).name() << '\n'
<< typeid(unsigned char ).name() << '\n'
<< typeid(short ).name() << '\n'
<< typeid(unsigned short ).name() << '\n'
<< typeid(int ).name() << '\n'
<< typeid(unsigned int ).name() << '\n'
<< typeid(long ).name() << '\n'
<< typeid(unsigned long ).name() << '\n'
<< typeid(long long ).name() << '\n'
<< typeid(unsigned long long).name() << '\n'
<< typeid(float ).name() << '\n'
<< typeid(double ).name() << '\n'
<< typeid(long double ).name() << '\n';
c
h
s
t
i
j
l
m
x
y
f
d
e
Composite Types
class Foobar {};
cout << typeid(bool * ).name() << '\n'
<< typeid(const bool *).name() << '\n'
<< typeid(bool ****** ).name() << '\n'
<< typeid(int[3] ).name() << '\n'
<< typeid(int[3][4][5]).name() << '\n'
<< typeid(char *[] ).name() << '\n'
<< typeid(main ).name() << '\n'
<< typeid(Foobar ).name() << '\n';
Pb
PKb
PPPPPPb
A3_i
A3_A4_A5_i
A_Pc
FivE
Z4mainE6Foobar
Polymorphic Example
For RTTI (Run-Time Type Identification), a class
must
have at least one virtual function.
struct Base { virtual void foo(){} };
struct D1 : Base {};
struct D2 : Base {};
void foo(Base *b) {
cout << ((typeid(*b) == typeid(D1)) ? "D1\n" : "D2\n");
}
int main() {
D1 d1;
D2 d2;
foo(&d1);
foo(&d2);
}
D1
D2
dynamic_cast
dynamic_cast
converts a base class
pointer to a derived class
pointer.
If it fails, you get a null pointer.
struct Base { virtual void foo(){} };
struct D1 : Base {};
struct D2 : Base {};
void foo(Base *b) {
D1 *p = dynamic_cast<D1 *>(b);
cout << (p ? "D1\n" : "D2\n");
}
int main() {
D1 d1;
D2 d2;
foo(&d1);
foo(&d2);
}
D1
D2
Guilt
- Use of
typeid()
or dynamic_cast
indicates that your
class hierarchy is incorrect.
- If you’re asking “Is this pointer such-and-such a type?”,
consider adding a method that answers the real question
- However, sometimes you’re stuck with an existing class
hierarchy, and so you do what you have to.