rtti
RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
C++ 里通过虚函数增加额外信息的方法实现了RTTI。GCC和VS的实现也大同小异,并且都有专门的设置来开关来禁止或使用RTTI。
和RTTI相关操作的函数是typeid和dynamic_cast.
这里将结合前面的内容,自己实现一个RTTI。
1.定义
1 namespace blog { 2 class Object; 3 class Type 4 { 5 public: 6 struct Rtti 7 { 8 public: 9 typedef const Rtti& (*TypeId)(void); 10 public: 11 Rtti( 12 const Type* baseType, 13 const char *pname, 14 long long hash, 15 Object* (*constructor)() = nullptr 16 ); 17 Object* newObject()const; 18 const Type* Id()const; 19 const char* getName()const; 20 long long getHash()const; 21 const Type* getBaseTypes()const { return _baseType; } 22 23 bool isExactKindOf(const Type& type) const; 24 bool isKindOf(const Type& baseRtti) const; 25 26 private: 27 const Type* _baseType; 28 const char* _name; 29 long long _hash; 30 Object* (*_constructor)(); 31 }; 32 public: 33 Type(); 34 Type(const Rtti::TypeId type); 35 bool operator == (Type type)const; 36 bool operator != (Type type)const; 37 const char* getName()const; 38 long long getHash()const; 39 Object* newObject()const; 40 41 bool isKindOf(Type id)const; 42 bool isExactKindOf(Type id)const; 43 const Type* getBaseTypes()const; 44 45 typedef Rtti::TypeId ID; 46 const static Type vNone; 47 private: 48 Rtti::TypeId _typeid; 49 }; 50 }
其中Object是将实现RTTI的类,Type是封装类的TypeId,其中的struct Rtti将保存类的基本信息
下面定义Object基础类以及其派生类
1 class Object : public Memory 2 { 3 private: 4 static Object* New() { return new Object(); } 5 friend class Type; 6 public: 7 static const Type::Rtti& TypeId() 8 { 9 const static Type rtti[] = { nullptr }; 10 const static Type::Rtti inst(rtti, "Object", "Object"_hash, New); 11 return inst; 12 } 13 virtual Type getType()const { return TypeId; } 14 }; 15 class DerivedObject : public Object 16 { 17 private: 18 static Object* New() { return new DerivedObject(); } 19 public: 20 static const Type::Rtti& TypeId() 21 { 22 const static Type rtti[] = { Object::TypeId,nullptr }; 23 const static Type::Rtti inst(rtti, "DerivedObject", "DerivedObject"_hash, New); 24 return inst; 25 } 26 virtual Type getType()const override { return TypeId; } 27 };
2.使用
1 Type objType = Object::TypeId; 2 Object* obj = new Object(); 3 Type pobjType = obj->getType(); 4 std::cout << pobjType.getName() << std::endl; 5 delete obj; 6 obj = new DerivedObject(); 7 std::cout << obj->getType().getName() << std::endl; 8 std::cout << obj->getType().isKindOf(objType) << std::endl; 9 switch (obj->getType().getHash()) 10 { 11 case "Object"_hash: 12 std::cout << "Object" << std::endl; 13 break; 14 case "DerivedObject"_hash: 15 std::cout << "DerivedObject" << std::endl; 16 break; 17 default: 18 break; 19 } 20 delete obj;
3.结果
Object DerivedObject true DerivedObject
4.优缺点
该代码实现的是单继承的,且不能使用在模板类上。
可以通过宏定义的方式,简化代码书写。
1 class DerivedObject : public Object 2 { 3 DECL_RTTI(DerivedObject, Object); 4 };