down-casting to unknown derived class

Hey there,

Is it possible to cast a pointer to an Object to a pointer of the real derived type without knowing the exact type?

Something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class A
{
    // some general information 
};
class B : public A
{
    // some information about B
};
class C : public A
{
    // some information about C
};

int func(B& b) { /* doing something with b */ }
int func(C& c) { /* doing something with c */ }

int main(void)
{
    std::vector<A*> elements;
    elements.push_back(new B());
    elements.push_back(new C());
    elements.push_back(new C());
    elements.push_back(new B());
    elements.push_back(new C());
    
    for(int i = 0; i < elements.size; ++i)
        func((DERIVED_TYPE&)*elements[i]);
}

The Makro DERIVED_TYPE obviously does not exist but is there something that let's me cast to the derived type?
If you don't know what the type is, how do you expect to use it at all?

You probably want func to be a virtual member function instead of a free function - then you can just let the language call the most derived function for you.
This question doesn't really make sense, since the whole point of polymorphism is to have the parent class act as a "I don't know exactly what type of object I have" interface. Downcasting is generally not necessary and should be avoided.

So what you are illustrating there is not possible. The compiler needs to know which version of func() to call at compile time, but downcasting can only happen at run time.

However, what you are illustrating is kind of poorly designed... and the same thing could be accomplished more reasonably with polymorphism like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class A
{
    // ...
    virtual int func() = 0;  // pure virtual interface
};
class B : public A
{
    // ...
    virtual int func() override     { /* doing something with b */ }
};
class C : public A
{
    // ...
    virtual int func() override     { /* doing something with c */ }
};

//  Get rid of these -- they are ill formed
// int func(B& b) { /* doing something with b */ }  
// int func(C& c) { /* doing something with c */ }

int main()  // <- (void) as a param list is a weird C thing.  You don't need/want it in C++
{
    std::vector<A*> elements;
    elements.push_back(new B());
    elements.push_back(new C());
    elements.push_back(new C());
    elements.push_back(new B());
    elements.push_back(new C());
    
    for(int i = 0; i < elements.size; ++i)
        elements[i]->func();  // <- just call the virtual function
}



EDIT: ninja'd by LB
Last edited on
damn it, I knew you'd come with polymorphism with that little example...
I'll give you the real example in this post but first let's make a few things clear

Disch wrote:
So what you are illustrating there is not possible. The compiler needs to know which version of func() to call at compile time, but downcasting can only happen at run time.
I though dynamic_cast is also executed at runtime, at least the answer in this thread on stackoverflow says so.
http://stackoverflow.com/questions/2253168/dynamic-cast-and-static-cast-in-c

LB wrote:
If you don't know what the type is, how do you expect to use it at all?
It should call the correct function, in that function decleration I know what type it is and use it.
And to my knowledge (I might be wrong) the real type of the object is stored somewhere in memory so I think it should be possible somehow.

Disch wrote:
This question doesn't really make sense
Yeah, you're probably right in this context.



So now to the "real problem"
I try to make a State-Mashine class where I want to just write event and state-classes without modifying the State-Mashine itself.

I have a few Events. I loop through them and check if any of them occured.
If one of them occured I want to call the corresponding method in my State-class.

In the current code all events allways occur but that's just for testing-reason.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Event-System-Test
#include <iostream>
#include <typeinfo>
#include <vector>

// State Mashine Part - should not need to be changed
class IEvent { public: virtual operator bool() = 0; };
class AState
{
public:
    virtual void Event(IEvent& event) 
    {
        // std::cout << typeid(*this).name() << std::endl;
        try { Event(dynamic_cast<DERIVED_TYPE&>(event)); }
        catch(...) { std::cout << "casting error" << std::endl; }
    }
};

// project part - add and delete as many states and events as you like
class Event1 : public IEvent { public: virtual operator bool() {return true;} } e1;
class Event2 : public IEvent { public: virtual operator bool() {return true;} } e2;

class State1 : public AState
{
public:
    virtual void Event(Event1&) { std::cout << "State1: 1 happened!" << std::endl; }
    virtual void Event(Event2&) { std::cout << "State1: 2 happened!" << std::endl; }
} s1;
class State2 : public AState
{
public:
    virtual void Event(Event2&) { std::cout << "State2: 2 happened!" << std::endl; }
} s2;

int main()
{
    std::vector<IEvent*> events;
    events.push_back(&e1);
    events.push_back(&e2);
    
    IState* current_state = &s1;
    
    for(int j = 0; j < 10; ++j)
    {
        for(int i = 0; i < events.size(); ++i)
            if(events[i])
                current_state->Event(*events[i]);
                
        if(current_state== &s1)
            current_state= &s2;
        else
            current_state= &s1;
    }
    
    return 0;
}

http://cpp.sh/9xgt
Last edited on
You need to use a different approach if you want to do this. In my event system I use a subscriber approach - classes extend the listener for the event types they want to listen to, and so event classes always know who is listening to them. All they have to do is loop through that list and notify each of their subscribers. This way you only need to know about the type that subscribers derive from, not the subscribers themselves.
So does that mean that it is not possible to cast down to the real type?

I allready have a working state mashine.
The state derives from a class inside the event class which is capeable of calling the event.
All Events are automatically added to the state-mashine-events when they are used by a state. (the events don't get deleted after they aren't needed anymore though)

Well, if this here won't work I'll just stick to my working state mashine
http://cpp.sh/2vwm
Gamer2015 wrote:
So does that mean that it is not possible to cast down to the real type?
Yes. The type of a variable or expression must be known at compile time. The type of an object can vary at runtime. This is true of most languages.
Last edited on
Why does dynamic_cast exist if the type has to be known at compile time and dynamic_cast casts at run time?
http://stackoverflow.com/a/1255015/1959975

Maybe the name is misleading.
okey thank you! :)
Topic archived. No new replies allowed.