Programmatically getting the name of a derived class - c++

I am attempting to do something like:
class Base {
public:
Base() {
cout << typeid(*this).name() << endl;
}
...
};
class Derived : public Base { ... }
class MoreDerived : public Derived { ... }
Derived d;
MoreDerived m;
Problem is, I always get Base printed to the screen, when I need to see Derived and MoreDerived. Is there a way to get typeid to work this way with derived classes? Or is there another approach besides typeid?
Note: I am adding functionality to an already coded suite, so I don't want to have to add a virtual method to the base class where the derived classes return this value themselves. Also, not worried about runtime overhead, this will be part of a debug compile switch.

In the constructor Base(), the object is still a "Base" instance. It will become a Derived instance after the Base() constructor. Try to do it after the construction and it will work.
See for example :
Avoiding virtual methods in constructor
Never Call Virtual Functions during Construction or Destruction

You can't do that from within a constructor (or destructor) - neither with typeid nor with a virtual method. The reason is while you're in a constructor the vtable pointer is set to the base class being constructed, so the object is of base class and no amount of polymorphism will help at that point.
You have to execute that code after the most derived class has been constructed. One option would be to use a factory function:
template<class T>
T* CreateInstance()
{
T* object = new T();
cout << typeid(*object).name() << endl;
return object;
}

Another option is to provide a virtual toName() function
struct Object{
virtual std::string toName() const = 0;
}
struct Base: Object{
std::string toName()const{ return "Base"; }
}
struct Derived: Base, Object{
std::string toName()const{ return "Derived"; }
This might get tedious since you need to manually create each toName function. But the advantage it gives you is to provide your own custom name.

Related

typeid() returning wrong type [duplicate]

I am attempting to do something like:
class Base {
public:
Base() {
cout << typeid(*this).name() << endl;
}
...
};
class Derived : public Base { ... }
class MoreDerived : public Derived { ... }
Derived d;
MoreDerived m;
Problem is, I always get Base printed to the screen, when I need to see Derived and MoreDerived. Is there a way to get typeid to work this way with derived classes? Or is there another approach besides typeid?
Note: I am adding functionality to an already coded suite, so I don't want to have to add a virtual method to the base class where the derived classes return this value themselves. Also, not worried about runtime overhead, this will be part of a debug compile switch.
In the constructor Base(), the object is still a "Base" instance. It will become a Derived instance after the Base() constructor. Try to do it after the construction and it will work.
See for example :
Avoiding virtual methods in constructor
Never Call Virtual Functions during Construction or Destruction
You can't do that from within a constructor (or destructor) - neither with typeid nor with a virtual method. The reason is while you're in a constructor the vtable pointer is set to the base class being constructed, so the object is of base class and no amount of polymorphism will help at that point.
You have to execute that code after the most derived class has been constructed. One option would be to use a factory function:
template<class T>
T* CreateInstance()
{
T* object = new T();
cout << typeid(*object).name() << endl;
return object;
}
Another option is to provide a virtual toName() function
struct Object{
virtual std::string toName() const = 0;
}
struct Base: Object{
std::string toName()const{ return "Base"; }
}
struct Derived: Base, Object{
std::string toName()const{ return "Derived"; }
This might get tedious since you need to manually create each toName function. But the advantage it gives you is to provide your own custom name.

How to declare an "unknown" derived class as base class as a member and allow the derived version of member function to be called?

I am currently trying to set a member of a class (myClass) to be some derived classes (Derived1, Derived2,...) of a Base class. Since the class don't know which derived class it is, the member type is set to Base class, it is only set to the derived class when constructed.
The derived classes all have a common member function which is implemented differently (Base class has a virtual version). However, when the this function is called from myClass, it always call the Base class version rather than the derived classes.
class Base
{
public:
Base(){}
virtual void who() { cout << "this is Base"; }
}
class Derived1 : public Base
{
public:
Derived1() : Base() {}
void who() { cout << "this is Derived1"; }
}
class myClass
{
private:
Base unknownDerived;
public:
myClass(const Base& inputDerived) { unknownDerived = inputDerived; }
void whosthere() { unknownDerived.who(); }
}
The output above is "this is Base", the Base class version is called instead.
Is there a way to include a member without specifying the actual derived class it is, but be able to call its specific function ( who() )?
thanks a lot!
When you declare Base as a member, Base is what you actually get. Even if you assign a Derived type to it, you experience what's called "slicing", where only the Base part of the derived object is copied, and your object is still a Base.
In C++, polymorphism only works through pointers and through references.
To make a real member object (not an indirection to the object) in myClass, you will need to make myClass have a template parameter, and you can decide at compile time what type it will be. Otherwise, you must use pointers and/or references.
Now you have to be clear about memory ownership, and proper cleanup. You may make the caller transfer the ownership of the object (by taking a unique_ptr) or you might insist that Base has a virtual clone() function to create a deep copy of the object. Further, you most likely will need a virtual destructor in your base class as well.

C++ : Automatically run function when derived class is constructed

So I recently accidentally called some virtual functions from the constructor of a base class, i.e. Calling virtual functions inside constructors.
I realise that I should not do this because overrides of the virtual function will not be called, but how can I achieve some similar functionality? My use-case is that I want a particular function to be run whenever an object is constructed, and I don't want people who write derived classes to have to worry about what this is doing (because of course they could call this thing in their derived class constructor). But, the function that needs to be called in-turn happens to call a virtual function, which I want to allow the derived class the ability to override if they want.
But because a virtual function gets called, I can't just stick this function in the constructor of the base class and have it get run automatically that way. So I seem to be stuck.
Is there some other way to achieve what I want?
edit: I happen to be using the CRTP to access other methods in the derived class from the base class, can I perhaps use that instead of virtual functions in the constructor? Or is much the same issue present then? I guess perhaps it can work if the function being called is static?
edit2: Also just found this similar question: Call virtual method immediately after construction
If really needed, and you have access to the factory.
You may do something like:
template <typename Derived, typename ... Args>
std::unique_ptr<Derived> Make(Args&&... args)
{
auto derived = std::make_unique<Derived>(std::forward<Args>(args));
derived->init(); // virtual call
return derived;
}
There is no simple way to do this. One option would be to use so-called virtual constructor idiom, hide all constructors of the base class, and instead expose static 'create' - which will dynamically create an object, call your virtual override on it and return (smart)pointer.
This is ugly, and what is more important, constrains you to dynamically created objects, which is not the best thing.
However, the best solution is to use as little of OOP as possible. C++ strength (contrary to popular belief) is in it's non-OOP specific traits. Think about it - the only family of polymorphic classess inside standard library are streams, which everybody hate (because they are polymorphic!)
I want a particular function to be run whenever an object is constructed, [... it] in-turn happens to call a virtual function, which I want to allow the derived class the ability to override if they want.
This can be easily done if you're willing to live with two restrictions:
the constructors in the entire class hierarchy must be non-public, and thus
a factory template class must be used to construct the derived class.
Here, the "particular function" is Base::check, and the virtual function is Base::method.
First, we establish the base class. It has to fulfill only two requirements:
It must befriend MakeBase, its checker class. I assume that you want the Base::check method to be private and only usable by the factory. If it's public, you won't need MakeBase, of course.
The constructor must be protected.
https://github.com/KubaO/stackoverflown/tree/master/questions/imbue-constructor-35658459
#include <iostream>
#include <utility>
#include <type_traits>
using namespace std;
class Base {
friend class MakeBase;
void check() {
cout << "check()" << endl;
method();
}
protected:
Base() { cout << "Base()" << endl; }
public:
virtual ~Base() {}
virtual void method() {}
};
The templated CRTP factory derives from a base class that's friends with Base and thus has access to the private checker method; it also has access to the protected constructors in order to construct any of the derived classes.
class MakeBase {
protected:
static void check(Base * b) { b->check(); }
};
The factory class can issue a readable compile-time error message if you inadvertently use it on a class not derived from Base:
template <class C> class Make : public C, MakeBase {
public:
template <typename... Args> Make(Args&&... args) : C(std::forward<Args>(args)...) {
static_assert(std::is_base_of<Base, C>::value,
"Make requires a class derived from Base");
check(this);
}
};
The derived classes must have a protected constructor:
class Derived : public Base {
int a;
protected:
Derived(int a) : a(a) { cout << "Derived() " << endl; }
void method() override { cout << ">" << a << "<" << endl; }
};
int main()
{
Make<Derived> d(3);
}
Output:
Base()
Derived()
check()
>3<
If you take a look at how others solved this problem, you will notice that they simply transferred the responsibility of calling the initialization function to client. Take MFC’s CWnd, for instance: you have the constructor and you have Create, a virtual function that you must call to have a proper CWnd instantiation: “these are my rules: construct, then initialize; obey, or you’ll get in trouble”.
Yes, it is error prone, but it is better than the alternative: “It has been suggested that this rule is an implementation artifact. It is not so. In fact, it would be noticeably easier to implement the unsafe rule of calling virtual functions from constructors exactly as from other functions. However, that would imply that no virtual function could be written to rely on invariants established by base classes. That would be a terrible mess.” - Stroustrup. What he meant, I reckon, is that it would be easier to set the virtual table pointer to point to the VT of derived class instead of keep changing it to the VT of current class as your constructor call goes from base down.
I realise that I should not do this because overrides of the virtual function will not be called,...
Assuming that the call to a virtual function would work the way you want, you shouldn't do this because of the invariants.
class B // written by you
{
public:
B() { f(); }
virtual void f() {}
};
class D : public B // written by client
{
int* p;
public:
D() : p( new int ) {}
void f() override { *p = 10; } // relies on correct initialization of p
};
int main()
{
D d;
return 0;
}
What if it would be possible to call D::f from B via VT of D? You will use an uninitialized pointer, which will most likely result in a crash.
...but how can I achieve some similar functionality?
If you are willing to break the rules, I guess that it might be possible to get the address of desired virtual table and call the virtual function from constructor.
Seems you want this, or need more details.
class B
{
void templateMethod()
{
foo();
bar();
}
virtual void foo() = 0;
virtual void bar() = 0;
};
class D : public B
{
public:
D()
{
templateMethod();
}
virtual void foo()
{
cout << "D::foo()";
}
virtual void bar()
{
cout << "D::bar()";
}
};

Calling overloaded method with derived class

There is something that I don't manage to do with derived class.
Basically, I have one base class with an interact method, which takes another base class object as an argument. I then have a derived class, and I want it to overload the interact method - derived class objects should interact in their own style. So far so good, using virtual method I get the behaviour I want. However, I would also like to overload the interact method so it can take a derived class object as an argument.
Now, I have an object with a baseclass parameter. When I create such an object with a derived class as parameter and I make it interact with another object also created with a derived class as paramater, it does call the interact method of the derived class (as expected) but consider the method using the baseclass parameter. Is there a way to make it use the other method ?
The code is below, I hope this is clearer with it
#include <iostream>
class BaseClass{
public:
BaseClass();
virtual ~Baseclass();
virtual void interact(BaseClass* interaction_target){std::cout << "base class interaction" << std::endl;}
};
class DerivedClass : BaseClass{
public:
DerivedClass();
virtual ~DerivedClass();
virtual void interact(BaseClass* interaction_target){std::cout << "derived class interaction" << std::endl;}
virtual void interact(DerivedClass* interaction_target){std::cout << "interaction eased by the fact that two DerivedClass object are interacting" << std::endl;}
};
class MyObject{
protected:
BaseClass* interactor;
public:
MyObject(BaseClass* param) : interactor(param){}
virtual ~MyObject();
void ObjectInteraction(MyObject interaction_target){interactor->interact(interaction_target.interactor);}
};
int main(){
MyObject first_obj(new DerivedClass());
MyObject sec_obj(new DerivedClass());
first_obj.ObjectInteraction(sec_obj); // prints derived class interactions, whereas I would like
// it to use the second method ie. interact(DerivedClass*)
return 0;
}
Is there anyway to do this at all ?
Yes. What you're trying to do here is called "double dispatch," or more generally, "multiple dispatch." C++ doesn't support it directly (some languages do), but you can implement it yourself using the Visitor Pattern.

method chaining with polymorphism c++

Is it possible to write fluent chanining methods that return a derived type? Consider the following two classes:
class Base {
protected:
std::string mFoo;
public:
Base& withFoo(std::string foo) {
mFoo = foo;
return *this;
}
};
class Derived : public Base {
protected:
std::string mBar;
public:
Derived& withBar(std::string bar) {
mBar = bar;
return *this;
}
void doOutput() {
std::cout << "Foo is " <<
mFoo << ". Bar is " <<
mBar << "." << std::endl;
}
};
I would then like to build my object and use it like this:
Derived d;
d.withFoo("foo").withBar("bar").doOutput();
This of course fails since withFoo returns a Base. Since all my with methods simply set member variables, I can specify the derived withs first. The problem is my builder method (doOutput in the example above) would then need to be a separate statement.
Derived d;
d.withBar("this is a bar")
.withFoo("this is my foo");
d.doOutput();
My question is whether there is some way for withFoo to return an unknown derived type so that Base may be used seamlessly with multiple derived classes (after all, *this is a Derived, although Base (correctly) is unaware of the fact).
For a more concrete example, I'm writing a few classes to access a REST server. I have a RestConnection class with method withUrl, a PostableRest class with methods withParam and doPost, and a GettableRest class with doGet. I suspect this is not possible and will probably try cramming a bunch of virtual methods into RestConnection but I hate to do that when there are multiple withParams overloaded, some of which don't make sense to include in a GET parameter list.
Thanks in advance!
I think you could utilize CRTP here, something like the following, where the derived class tells the base what type it is:
class Base
{
// Abstract/virtual interface here.
};
template <class Derived>
class Base_T : public Base
{
private:
std::string mFoo;
public:
Derived& withFoo(std::string foo) {
mFoo = foo;
return *static_cast<Derived*>(this);
}
};
class Derived : public Base_T<Derived> {
private:
std::string mBar;
public:
Derived& withBar(std::string bar) {
mBar = bar;
return *this;
}
void doOutput() {
std::cout << "Foo is " <<
mFoo << ". Bar is " <<
mBar << "." << std::endl;
}
};
Take a look at Curiously recurring template pattern.
If Base is an abstract type (only instantiated in its subclasses) then make it a template taking type name. Your Derive will extend the template - e.g. Derived : public Base<Derived>. If Base is a concrete type - then you will need to introduce a new abstract class that would be a base type for Base and Derived.
This way withFoo can be templated to return real type.
You options are either CRTP (as Mark B illustrated), or using runtime dispatch on the variable name, eg.
Derived d;
d.with("Foo", "foo").with("Bar", "bar").doOutput();
this won't be particularly performant, but it's very flexible, and a good match for protocols which can take arbitrary fields.
Since your types are not polymorphic (no virtual functions) Base has no knoweledge of Derived.
You can reach you objective esentially with static polymorphism:
template<class Derived>
class Base {
protected:
std::string mFoo;
public:
Derived& withFoo(std::string foo) {
mFoo = foo;
return static_cast<Derived&>(*this);
}
};
class Derived : public Base<Derived> {
protected:
......
}
The drawback is that there is anymore a Base class, but as many Base instanciation as are the possible derived, hence you cannot anymore have a Base& or Base* pointing to whatever Derived.
If you need a common-base to collect, you need another CommonBase (not templetized) from which Base can derive from.
Another possibility is making Base (the old one) polimorphic by making withFoo virtual.
At that point, in Derived, you can override withFoo to return the Derived& covariant type:
class Base
{
...
virtual Base& withFoo(...);
...
virtual ~Base() {} //just to make all the hierarchy destructible through base
};
class Derived: public Base
{
...
virtual Derived& withFoo(type arg)
{ return static_cast<Derived&>(Base::withFoo(arg)); }
...
};
This still embrace the classic OOP paradigm, but adds run-time overhead (the vtables) and has the disadvantage it is based on a feature (covariant return type of virtual functions) not all compilers support.