Example: rtti_example1
Example console output:
Part 1:
RTTI Foo (static): Foo class: Bar class: Bar Is Foo? => No Is BarBase? => Yes Is Bar? => Yes specificBarMethod: reached.
Part 2:
Known class: Bar, children of BarBase Known class: BarBase, children of CObject Known class: CObject, children of (none) Known class: Foo, children of CObject Known class: Bar, children of BarBase specificBarMethod: reached.
C++ example source code:
/* +------------------------------------------------------------------------+ | Mobile Robot Programming Toolkit (MRPT) | | https://www.mrpt.org/ | | | | Copyright (c) 2005-2023, Individual contributors, see AUTHORS file | | See: https://www.mrpt.org/Authors - All rights reserved. | | Released under BSD License. See: https://www.mrpt.org/License | +------------------------------------------------------------------------+ */ #include <mrpt/rtti/CObject.h> #include <iostream> #include <memory> namespace MyNS { class Foo : public mrpt::rtti::CObject { public: Foo() {} DEFINE_MRPT_OBJECT(Foo, MyNS) void printName() { std::cout << "printName: Foo" << std::endl; } }; class BarBase : public mrpt::rtti::CObject { public: BarBase() {} DEFINE_VIRTUAL_MRPT_OBJECT(BarBase) virtual void printName() { std::cout << "printName: BarBase" << std::endl; } }; class Bar : public BarBase { public: Bar() {} DEFINE_MRPT_OBJECT(Bar, MyNS) void printName() override { std::cout << "class: Bar" << std::endl; } void specificBarMethod() { std::cout << "specificBarMethod: reached." << std::endl; } }; } // namespace MyNS IMPLEMENTS_MRPT_OBJECT(Foo, mrpt::rtti::CObject, MyNS) IMPLEMENTS_VIRTUAL_MRPT_OBJECT(BarBase, mrpt::rtti::CObject, MyNS) IMPLEMENTS_MRPT_OBJECT(Bar, MyNS::BarBase, MyNS) void Test_UserTypes() { using namespace MyNS; const auto id_foo = CLASS_ID(Foo); std::cout << "RTTI Foo (static): " << id_foo->className << std::endl; // Pointers: Bar::Ptr pBar = std::make_shared<Bar>(); BarBase::Ptr pBase = mrpt::ptr_cast<BarBase>::from(pBar); mrpt::rtti::CObject::Ptr pObj = mrpt::ptr_cast<mrpt::rtti::CObject>::from(pBar); pBar->printName(); pBase->printName(); std::cout << "Is Foo? => " << (IS_DERIVED(*pObj, Foo) ? "Yes\n" : "No\n"); std::cout << "Is BarBase? => " << (IS_DERIVED(*pObj, BarBase) ? "Yes\n" : "No\n"); std::cout << "Is Bar? => " << (IS_DERIVED(*pObj, Bar) ? "Yes\n" : "No\n"); if (IS_CLASS(*pObj, Bar)) { auto pBar2 = mrpt::ptr_cast<Bar>::from(pObj); pBar2->specificBarMethod(); } } void do_register() { // Register with explicit namespace: mrpt::rtti::registerClass(CLASS_ID_NAMESPACE(Foo, MyNS)); { // Register without explicit namespace: using namespace MyNS; mrpt::rtti::registerClass(CLASS_ID(BarBase)); mrpt::rtti::registerClass(CLASS_ID(Bar)); mrpt::rtti::registerClassCustomName("MyNS::Bar", CLASS_ID(Bar)); } } void Test_UserTypesFactory() { do_register(); // Test register: { const auto& allClasses = mrpt::rtti::getAllRegisteredClasses(); for (const auto& cl : allClasses) { std::cout << "Known class: " << cl->className << ", children of " << (cl->getBaseClass ? cl->getBaseClass()->className : "(none)") << std::endl; } } // Test factory: { mrpt::rtti::CObject::Ptr pObj = mrpt::rtti::classFactory("MyNS::Bar"); if (IS_CLASS(*pObj, MyNS::Bar)) { auto pBar = mrpt::ptr_cast<MyNS::Bar>::from(pObj); pBar->specificBarMethod(); } } } int main(int argc, char** argv) { try { Test_UserTypes(); Test_UserTypesFactory(); return 0; } catch (const std::exception& e) { std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl; return -1; } }