Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing derived class name in base class

Tags:

c++

How can I print out the derived class name from the base class without chaining constructors all the way down. In other words is it possible to do this strictly from the base class without adding code in each derived class?

This is an example of what I got, and if there's a way I'd like to get rid of the constructor chaining.

EDIT: Ideally I am looking for something to add into the base class without having to edit all derived classes. At the moment my real code has got ~17 classes(with need for more), so something that could do the job straight from the base class would be ideal. Even if it's compiler specific (g++ or clang).

#include <iostream>

class Base {
public:
    Base(std::string id) {
            std::cout<<"Creating "<<id<<std::endl;
    }
};

class Child : Base {
public:
    Child(std::string id) : Base(id) {}
    Child() : Base(typeid(this).name()) {}
};

class GrandChild : Child {
public:
    GrandChild(std::string id) : Child(id) {}
    GrandChild() : Child(typeid(this).name()) {}
};

class GrandGrandChild : GrandChild {
public:
    GrandGrandChild(std::string id) : GrandChild(id) {}
    GrandGrandChild() : GrandChild(typeid(this).name()) {}
};



int main() {
    GrandGrandChild *A = new GrandGrandChild();
    GrandChild *B = new GrandChild();
    Child *C = new Child();

    return 0;
}

Which prints:

Creating GrandGrandChild
Creating GrandChild
Creating Child

But with compiled added prefix.

like image 659
NFA Avatar asked Jun 05 '12 09:06

NFA


1 Answers

There is unfortunately no easy solution.

The problem is that constructing polymorphic objects is quite complicated, at the moment you are building the Base subpart of a Child class, you are building a Base still, not a Child (because trying to access Child members would be non-sensical, they have not been built yet!)

As such, all the ways to retrieve dynamic information (known as RTTI or RunTime Type Information) are voluntarily locked down to prevent such mistake.

For symmetrical reasons, the same occur in the destructor.


Now, only the constructor and destructor are so locked down, therefore you can perfectly have a name() method that will happily return the true name of the dynamic type of the instance in all other cases:

class Base {
public:
    std::string name() const { return typeid(*this).name(); }
};

It will work... unless you invoke it from a constructor or destructor in which case it will report the static type.

Now, as far as the "bizarre" output, each implementation (compiler) is allowed to provide its own output here (and they need not even be different for different types, crazy eh!). You seem to be using gcc or clang.

There are demanglers to interpret such output, or if your program is simple enough and their interface scares you, you might simply try to parse it manually to remove the cruft. The name of the class should appear fully, it'll just be preceded with some nonsense (namespaces and numbers essentially).

like image 199
Matthieu M. Avatar answered Oct 06 '22 01:10

Matthieu M.