Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving a c++ class name programmatically

Tags:

c++

class

macros

I was wondering if it is possible in C++ to retrieve the name of a class in string form without having to hardcode it into a variable or a getter. I'm aware that none of that information is actually used at runtime, therefor it is unavailable, but are there any macros that can be made to create this functionality?

Edit: May be helpful to note that I'm actually trying to retrieve the name of a derived class, and I'm using Visual C++ 2008 Express Edition.

like image 865
Morgan Avatar asked Jun 21 '09 20:06

Morgan


People also ask

How do I get the ClassName in C++?

Finally to Get the class name you'd do the following: ClassName< MyClass >::name(); Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function. DefineClassName( MyClass );

How do I return a class name?

The simplest way is to call the getClass() method that returns the class's name or interface represented by an object that is not an array. We can also use getSimpleName() or getCanonicalName() , which returns the simple name (as in source code) and canonical name of the underlying class, respectively.


2 Answers

You can use typeid:

#include <typeinfo>  std::cout << typeid(obj).name() << "\n"; 

However, the type name isn't standardided and may differ between different compilers (or even different versions of the same compiler), and it is generally not human readable because it is mangled.

On GCC and clang (with libstdc++ and libc++), you can demangle names using the __cxa_demangle function (on MSVC demangling does not seem necessary):

#include <cxxabi.h> #include <cstdlib> #include <memory> #include <string>  std::string demangle(char const* mangled) {     auto ptr = std::unique_ptr<char, decltype(& std::free)>{         abi::__cxa_demangle(mangled, nullptr, nullptr, nullptr),         std::free     };     return {ptr.get()}; } 

This will still not necessarily be a readable name — for instance, std::string is a type name for the actual type, and its complete type name in the current libstdc++ is std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >; by contrast, in the current libc++ it’s std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >. “Prettifying” type aliases is unfortunately not trivial.

like image 200
Konrad Rudolph Avatar answered Oct 19 '22 02:10

Konrad Rudolph


If you just want to check if it's certain class, then

typeid(obj) == typeid(CSubClass) 

will always work regardless of the implementations.

Otherwise, a convenient way is to declare:

virtual const char* classname() { return "CMyClass";} 

and implement per subclass.

like image 35
fchen Avatar answered Oct 19 '22 00:10

fchen