C++ on iPhone: Part 3, Run Time Type Identification

In this third article on C++ programming on the iPhone platform, I will be covering RTTI, or Run Time Type Identification. This C++ language feature is often unsupported on mobile platforms due to the usual "code bloat" reasons. So, let’s take a look at the iPhone and see what it has to offer.

There are two main elements of RTTI in C++, namely type identification, and type casting.

1. Type identification. The C++ keyword typeid is an operator used to obtain information about the run time type of an object. It is used as follows:

1
2
3
4
5
6
7
8
9
10
11
12
// typeid only works on polymorphic classes,
// that is, classes with at least one virtual method
 
class PolymorphicClass
{
public:
virtual void virtualMethod()
{
}
} polymorphicObject;
 
const std::type_info &info = typeid (polymorphicObject);

In this case, std::type_info is a type that will receive the RTTI information about our polymorphicObject – we’ll actually get a reference to a std::type_info back from the typeid operator. The std::type_info class can be used to obtain the actual name of the type of our polymorphicObject, as follows:

const char* name = info.name();

Which will yield a string representation of the class name, but not necessarily the actual class name. I believe the string returned is “implementation dependent” and as such may vary from compiler to compiler. We’ll see what we get on the iPhone shortly.

2. Dynamic type casting.
The C++ operator dynamic_cast allows casting "down" a polymorphic inheritance tree (ie, casting from a base class to a derived class). It operates on pointer (and reference) types and the syntax is as follows:

pointer to object of target type = dynamic_cast(pointer expression);
reference to object of target type = dynamic_cast(reference expression);

To see this in action, consider the following class definitions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Class InterfaceClass
{
public:
    virtual GeneralMethod()
    {
    }
};
 
Class SpecializedClass : public InterfaceClass
{
public:
    virtual void GenerealMethod()
    {
    }
    virtual void SpecializedMethod()
    {
    }
};

Then, let’s say we have a base class pointer that actually points to a specialized class.

InterfaceClass* interface = new SpecializedClass();

There is no way to call the method SpecializedMethod() from this base class pointer directly; however, if we know the pointer is to a SpecializedClass, we can use the dynamic_cast operator thus:

SpecializedClass* specialized = dynamic_cast<SpecializedClass*>(interface);

There is much more to this topic than I have space to go into here, but we’ve at least covered some of the basics. The question remaining is, “will it work in the iPhone”? In fact, this works perfectly well, and I’ve wrapped the above into an example you can try. Using the same project as the previous articles, I made myself new files rtti.cpp and rtti.h and added them to the project. In this case, I am not going to make a class called “rtti” but these files will hold our RTTI test code.

Our header file rtti.h looks like this:

1
2
3
4
5
6
7
8
// rtti.h
#ifdef __cplusplus
extern "C" {
#endif
	void rttiTest();
#ifdef __cplusplus
}
#endif

And rtti.cpp looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// rtti.cpp
 
#include "rtti.h"
#include <typeinfo>
#include <iostream>
 
using namespace std;
 
// test typeid
class PolymorphicClass
{
public:
	virtual void virtualMethod()
	{
	}
} polymorphicObject;
 
// test dynamic_cast
class InterfaceClass
{
public:
    virtual void GeneralMethod()
	{
	}
};
 
class SpecializedClass : public InterfaceClass
{
public:
    virtual void GenerealMethod()
	{
	}
    virtual void SpecializedMethod()
	{
		cout << "SpecializedMethod()" << endl;
	}
};
 
void rttiTest()
{
	const type_info &info = typeid (polymorphicObject);
 
	const char* name = info.name();
	cout << "typeid name of PolyMorphicClass is " << name << endl;
 
	InterfaceClass* interface = new SpecializedClass();
 
	// can't do this:
	// interface->SpecializedMethod();
 
	// but use dynamic_cast to down cast the pointer
	SpecializedClass* specialized = dynamic_cast<SpecializedClass*>(interface);	
 
	// and then this works fine:
	specialized->SpecializedMethod();
 
	// and for good measure print the names of pointee objects
	cout << "Run time type name of interface is " << typeid(*interface).name() << endl;
	cout << "Run time type name of specialized is " << typeid(*specialized).name() << endl;
}

Then I included rtti.h from main.m and added a called to the rttiTest() method at the top of main():

	rttiTest();

The console output when this is run on the iPhone is as follows:

typeid name of PolyMorphicClass is 16PolymorphicClass
SpecializedMethod()
Run time type name of interface is 16SpecializedClass
Run time type name of specialized is 16SpecializedClass

Notice the name given is “16PolymorphicClass”, which is pretty typical of the type of name you’ll see wen using typeid. It is useful for comparison purposes, if nothing else. I believe this is an artifact of the “mangling” that occurs to all C++ symbols during compilation. I’ve also added output to show the run time type names of the object pointed @ by interface and specialized, for good measure (they are the same, as you would expect).

To recap, we have shown through an extremely simple example that basic RTTI operations do in fact work on the iPhone. We saw that typeid gives us run time type info about an object, and that dynamic_cast correctly casts down a polymorphic class hierarchy.

In upcoming articles I will be moving on to examples of interaction between Objective C, Objective C++ and straight C++ code.

I would add as a footnote that dynamic_cast is potentially a performance hog and can often be avoided in favor of the alternate static_cast operator (which is resolved at compile time). Still, as a C++ language feature it is good to know that it is available.

  1. Just to confirm. Did you run these on the actual iPhone or just in the simulator? I would just be concerned with the simulator differing from the actual device since we know its set of libraries is different from OSX.

  2. I’ve used these features on the iphone extensively. they’re part of the ANSI standard and GNU G++ for ARM (the compiler used by xcode) fully supports them.

  3. Hello.
    These articles are pretty good, as not much people do care about C++ on iPhone…
    But please, could you continue with them?
    It´s no use when you stop on console-level programming.
    Something with handling touches, graphics, keyboards, GUIs, etc.?

    If you could do something like that, I would really thank you much.

Comments are closed.

  • Related Content by Tag