0

I have this abstract base class, and I want it to be able to get the name of the class deriving from it, whatever class that may be. I want to hide this functionality from the user, because I'm just using it to make the name of a log file or something. I've heard of typeid but I can't get this to compile. I would also settle for being able to get the name of the object, instead of the class.

#include <typeinfo>

class Base{ 
public:
    virtual void lol() = 0;
    std::string getName(); 
};

std::string Base::getName() {
    return typeid(*this);  // this doesn't work!
}


class Derived : public Base{
    void lol() {}; 
};

int main(int argc, char **argv) {

    Derived d;
    std::cout << d.getName() << "\n";

    return 0; }
Taylor
  • 1,797
  • 4
  • 26
  • 51
  • 2
    The types of identifying information you can get out of C++ are arcane (do not expect them to be human readable) and not portable. If you need to know the type of a derived class you almost always have an error in your design. Look at increasing the functionality of the base class with virtual functions. – user4581301 May 24 '18 at 22:33
  • @user4581301 interesting. Is there a typical way to automatically generate the names of log files? – Taylor May 24 '18 at 22:37
  • You are wanting a log file per class named after the class? This may be better done at compile time. I do not know if there is any truly portable way to do this, but [this linked answer](https://stackoverflow.com/a/15775519/4581301) to a similar question may be adaptable to your needs if you are using GCC. – user4581301 May 24 '18 at 22:45
  • 1
    Do you actually need the names to be automatically generated? Maybe just establish an idiom for providing the name explicitly, like some macro that would actually override the method returning the log name? Making it manual is definitely less cool, but may be actually more robust. – Frax May 24 '18 at 22:49

3 Answers3

1

Call name() on the typeid as seen here: type_info::name

return typeid(*this).name();

Incidentally, this does kinda make the getName() function a little redundant.

tdk001
  • 1,014
  • 1
  • 9
  • 16
1

You can take advantage of a preprocessor and use __PRETTY_FUNCTION__ in GCC and Clang or __FUNCTION__ in Visual C++.

#include <iostream>
#include <string>

class Base { 
public:
    virtual std::string getName();
};

std::string Base::getName() {
    return __PRETTY_FUNCTION__;
}

class Derived : public Base {
public:
    std::string getName() override {
        return __PRETTY_FUNCTION__;
    }
};

int main(int argc, char **argv) {
    Derived d;
    std::cout << d.getName() << "\n";
    return 0;
}

Unfortunately they return full method name, the example above outputs

virtual std::__cxx11::string Derived::getName()

and if you need it you can implement a helper function in Base that will extract a class name between last :: and space.

std::string getName() override {
    return extractClassName(__PRETTY_FUNCTION__);
}
273K
  • 29,503
  • 10
  • 41
  • 64
-2

There may be a few ways to do this...

I might 1) create an abstract property (or accessor function) in the base class like:

2) then in the constructor of the derived class, assign the name...then the base can use it and see it...