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 bas
Since you indicate this is for debugging, you can rely on virtual inheritance to avoid passing the name through all the intermediate derived classes, and instead pass it directly to the Base
. Also, Base
can be modified to take a template constructor to simplify things for the derived classes.
class Base {
public:
template <typename DERIVED>
Base (DERIVED *d) {
std::cout << "Creating " << typeid(*d).name() << std::endl;
}
};
class Child : virtual public Base {
public:
Child () : Base(this) {}
};
class GrandChild : public Child, virtual public Base {
GrandChild () : Base(this) {}
}
class GrandGrandChild : public GrandChild, virtual public Base {
GrandGrandChild () : Base(this) {}
}
you can provide an initialization function that needs to be called from each constructor.
class Base {
protected:
Base() { init(typeid(this).name()); }
void init(std::string id) {
std::cout<<"Creating "<<id<<std::endl;
}
};
You somehow need to make sure, that subsequent inits will safely supersede the changes of previous ones:
Creating P4Base
Creating P5Child
Creating P10GrandChild
Creating P15GrandGrandChild
Creating P4Base
Creating P5Child
Creating P10GrandChild
Creating P4Base
Creating P5Child
I intend to use it purely for debugging purposes, which is why something to throw into the base class would be convenient.
have you considered adding a macro to your code to print the debug output?
#ifdef DEBUG
#define PRINT_CLASSNAME std::cout<<"Creating "<<id<<std::endl;
#else
#define PRINT_CLASSNAME ;
#endif
You need to add it to your constructors once, but if you want to disable it (temporarily) you just undefine it?
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).