How can I get the class name from a C++ object?

Is it possible to get the object name too?

#include<cstdio>

class one {
public:
    int no_of_students;
    one() { no_of_students = 0; }
    void new_admission() { no_of_students++; }
};

int main() {
    one A;
    for(int i = 0; i < 99; i++) {
        A.new_admission();
    }
    cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
        <<A.no_of_students<<" students";
}

where I can fetch the names, something like

[classname] = A.classname() = one
[objectname] = A.objectname() = A

Does C++ provide any mechanism to achieve this?


Solution 1:

You can display the name of a variable by using the preprocessor. For instance

#include <iostream>
#define quote(x) #x
class one {};
int main(){
    one A;
    std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
    return 0;
}

outputs

3one    A

on my machine. The # changes a token into a string, after preprocessing the line is

std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";

Of course if you do something like

void foo(one B){
    std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
    one A;
    foo(A);
    return 0;
}

you will get

3one B

as the compiler doesn't keep track of all of the variable's names.

As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use

#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
    one<int,one<double, int> > A;
    int status;
    char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
    std::cout<<demangled<<"\t"<< quote(A) <<"\n";
    free(demangled);
    return 0;
}

which gives me

one<int, one<double, int> > A

Other compilers may use different naming schemes.

Solution 2:

use typeid(class).name

// illustratory code assuming all includes/namespaces etc

#include <iostream>
#include <typeinfo>
using namespace std;

struct A{};
int main(){
   cout << typeid(A).name();
}

It is important to remember that this gives an implementation defined names.

As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.

EDIT 2:

#include <typeinfo>
#include <iostream>
#include <map>
using namespace std; 

struct A{
};
struct B{
};

map<const type_info*, string> m;

int main(){
    m[&typeid(A)] = "A";         // Registration here
    m[&typeid(B)] = "B";         // Registration here

    A a;
    cout << m[&typeid(a)];
}

Solution 3:

To get class name without mangling stuff you can use func macro in constructor:

class MyClass {
    const char* name;
    MyClass() {
        name = __func__;
    }
}

Solution 4:

Do you want [classname] to be 'one' and [objectname] to be 'A'?

If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.

Solution 5:

Just write simple template:

template<typename T>
const char* getClassName(T) {
  return typeid(T).name();
}

struct A {} a;

void main() {
   std::cout << getClassName(a);
}