I am trying to work on a project that will require me to determine a polymorphic object's type at runtime, so that I can cast it. An example of what I mean:
class A{
};
class B: public A{
public:
void foo(){
printf("B::foo()\n");
}
};
Later, I will have a bunch of B objects that are essentially stored as such:
std::vector<A*> v;
v.push_back(new B());
And I will need to call certain overloaded methods defined as:
void bar(B* b){
b->foo();
}
After passing in objects that are stored in v
. The problem that I am having is that in my actual use-case, I don't know the type of B
at compile-time, so I can't just call bar
by saying bar((B*)v.get(0));
The solution I have been thinking I might need is to somehow determine the type that each object is at runtime, so that I can cast it before passing it to bar
.
The solution I have tried so far was to use decltype
, but it didn't work for me because it just returns the static type of the value passed in, not the type at runtime.
Also, I do not want to use third party libraries for this project, since I would like to make it as small as possible.
Thank you for your help.
Edit:
I don't think I was clear enough in what I meant when I was describing my problem. In my actual use case (which is a bit long to try posting here, though I can post parts of it if necessary), I am trying to write a library in which there is a base class (represented here as A
) which can be extended by the user into their own custom classes (represented here as B
). In my example, B::foo()
is simply supposed to represent how each subclass of A
can have its own data members that are handled later by some method (represented in my example as bar
). This is also the reason why A
cannot simply have some virtual foo
method.
The main issue I'm having is, since B
is supposed to be user-defined, I don't know what it is at compile-time, but I do at link-time (since linking comes later). That is why the use of dynamic_cast
(as suggested by Sam and Remy) won't work, because from what I understand of it, it requires that I know every possibility of what B
could be, which I don't. Although it did look very close to what could work for me. If there was some way to get all possible subclasses (say, with preprocessor macros or templates), then I think this might be able to work.
I hope I've explained it better this time. Thank you again for your help.
Edit 2: Another clarifying point: In the actual project I am working on, I only want the user to be required to write their own B
classes and overload bar
to work with their custom classes. However, I don't want the user to be required to call bar
. Rather, I would like to have bar
be called from a base class (that I define). That is the main reason for even attempting to do this the way I am. That, and to see if I can.
Hope that clears everything up. Thank you again.
This is what virtual methods are for.
Declare the foo()
virtual method in A
, and you don't have to worry about doing ugly casts.
Alternatively, if A
has at least one virtual function -- and a virtual destructor will do -- you can try your luck with a dynamic_cast<>
.
In C++, (dynamic) polymorphism is the tool for this type of thing.
struct A {
virtual void foo() = 0;
virtual~A() {}
};
struct B : A {
void foo() override;
};
std::vector<std::unique_ptr<A>> vA;
vA.emplace_back(new B);
vA[0]->foo();
There is no need to find the actual type of the object pointed to by vA[0]
, the virtual
function call mechanism will find the correct function (in this case B::foo()
). Note the virtual
destructor of class A
. It guarantees that derived objects (of class B
) are correctly deleted from a pointer to A
(as kept by unique_ptr<A>
).
Of course, there is also the dynamic_cast<>
, which allows you to test whether the object is actually of a certain type:
auto ptr = dynamic_cast<B*>(vA[0].get());
if(ptr) // object is a B
std::cout<<" have B";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With