How to pass a derived pointer in a virtual function?

I'm looking to pass a base object pointer through a virtual function, and in overriden methods of the virtual function, I want them to recognize the derived pointer, not the base pointer. Here is an example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base{

};

class Derived : Base{

};

class ExternalClass{
public:
virtual void Function(Base *){
//code stops here, but this function does nothing, since I want the overriding function to be called
}
}

class ExternalClassDerived : ExternalClass{
public:
virtual void Function(Derived *p){
//do something with p
//however the code never reaches here
}
}


Here is my actual code, as the above example is a little sparse.
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
class WorldObject{
//...
};

class Entity : public WorldObject{
public:
Entity();
virtual void Update(){
    input->Update(this);
}
Input *input;
};

class Input{
public:
//...

    virtual void Update(WorldObject *){
    //this is where the function call ends, so nothing gets done because this
    //method is purposefully empty
    }
};

class MeleeEntityAI : public Input{
public:
	MeleeEntityAI(){}
	virtual ~MeleeEntityAI(){}

	virtual void Update(Entity *o);
};

void MeleeEntityAI::Update(Entity *o){
	//desired behavior, never called
}

Entity::Entity(){
    input = new MeleeEntityAI();
}


But if I ever call Function and pass it a Base pointer, then Function(Derived*) is never called; the call stops at Function(Base*). How can I get Function(Derived*) to be called when I am passing a Base* to it?
Last edited on
You are not overriding the method Function in ExternalClassDerived. In order to override a function, the function must have the the same number and types of arguments in the overriding function.

If you're accessing your ExternalClassDerived instance via a pointer or reference to ExternalClass all that is visible is the ExternalClass::Function(Base*) method, and since it isn't overridden, that is what is called.
ExternalClassDerived::Function(Base *) can check if it got a derived pointer:
1
2
3
4
5
6
void ExternalClassDerived::Function(Base *base){
    auto derived = dynamic_case<Derived *>(base);
    if (!derived)
        return;
    // derived is a valid pointer.
}
I see. So how do I accomplish the behavior defined in Function(Derived*) when I am passing a derived pointer but I only have access to Function(Base*)?

I''ve posted my actual code above, since I may have over-abstracted.
Last edited on
1
2
3
4
5
6
void ExternalClassDerived::Function(Base *base){
    auto derived = dynamic_case<Derived *>(base);
    if (!derived)
        return;
    // derived is a valid pointer.
}


I have heard to avoid casting at almost all costs. Is this really what you recommend here, or is it simply a solution that may not be desirable?
Avoid it if possible, since it's a fairly costly operation in most implementations. If the function definitely needs a Derived then you have no choice but to either dynamic_cast or to redesign.
You may want to google for double dispatch to see another approach to solving the problem.
You may want to google for double dispatch to see another approach to solving the problem.

I've implemented double dispatch for my collision resolution, but it seems so overkill here just to handle AI, since I'd have to forward declare every derived class.

I had no trouble getting it to work with double dispatch, but as my list of derived classes increases, this code may become a little unwieldly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Entity;
class MeleeEnemy;
class Jumper;
class WorldObject;

class Input{
public:
	Input(){
		ClearInputs();
	}
	virtual ~Input(){}

    //override these in derived classes from Input
	virtual void Update(Entity *g){}
	virtual void Update(MeleeEnemy *g){}
	virtual void Update(Jumper *g, /*and other params*/){}
//...
};
Last edited on
Topic archived. No new replies allowed.