Which function will be called? Inheritance

Hi,

I have UObject UAction. This object has a function StartAction(). I inherit from this class several Actions and override this function.

The question is: Which function is called when I do this?:

UActionCPP* action = NewObject<UActionCPP>(this, currentAction->GetFName(), RF_NoFlags, currentAction->GetDefaultObject());

//currentAction is TSubclassOf<UActionCPP> name; I init it in another function

action->StartAction();

Whenever I do this, nothing happens. I guess it calls the parent function which is empty. In java I would just type override, but here I cant do that. What do I do?

This is a basic example of how inheritance works. It’s not different from java, so I’m not sure what has gone wrong.

Though, the error might’ve come from your instantiation- I’m not sure why you’re using GetDefaultObject() if you just created the objects for this purpose.

This example is wrong.
Without virtual is shadowing not overriding.

Your example is wrong.
I am not making instance of Derived, I am making instance of Base but init it with Derived (Base = Derived).
In my case UActionCPP is Base and currentAction is Derived

So I added virtual in the base class and override in the child class

Base:
image
Derived:
image

It is still calling the base StartAction and not derived.

So something must be wrong with the way I make this object.

void USomeComponent::ExecuteAction()
{
	UActionCPP* action = NewObject<UActionCPP>(this, currentAction->GetFName(), RF_NoFlags, currentAction->GetDefaultObject());
	action->StartAction();
}

When I print out the currentAction->GetFName() I get the corrent class name

Why you explicitly pass template object(4th parameter)?

Because I have a variable that I can change in BP. And If i dont pass template, then it will not take the changes that I did in BP and leave the base values. But even without template, it doesnt work

Btw, if I print out action->GetFName() I get correct Name, If I do action->GetClass()->GetFName() I get the base class name. So I think that NewObject return UActionCPP objectref and not UAction_Derived objectref. So that is why it is not calling the correct function

Then how do I do it then?

This is what I would do in BP and it works:
image

The function executeAction in CPP should do the same as in the picture.

Class that I select in BP is TSubclassOfcurrentAction in CPP
outer is this in CPP
Info and data doesnt matter in this case
Return value in BP is ActionMove obj ref, in cpp it should be UAction* action

Second parameter of NewObject should be the class, not the class name.

That variant of NewObject that takes a string as second parameter, instantiates whatever type you pass in the template argument (ie. <UActionCPP> and not the subclass you expect). The string name is just a label as you see in the world outliner, it doesn’t necessarily reflect the underlying class of the object. Generally it’s best not to specify any name and let the engine generate one. The template shouldn’t be specified either.

Try this instead :

UActionCPP* action = NewObject<UActionCPP>(GetTransientPackage(), currentAction);
action->StartAction();

StartAction needs to be virtual for polymorphism (ie. overrideability) to work.

When overriding function in c++ subclass you might have to also specify the virtual keyword (I’m not sure if it’s truely required) :

virtual void StartAction() override;

To include blueprint overrideability support, use UFUNCTION(BlueprintNativeEvent).
Should look like this :

UFUNCTION(BlueprintNativeEvent)
void StartAction();  // no virtual, no implementation (auto-generated)
virtual void StartAction_Implementation();  // implement this in CPP, override this in CPP subclasses

Blueprint subclasses that override StartAction will actually override StartAction_Implementation, and using the “Call Parent” node will also redirect code towards native StartAction_Implementation.

1 Like

Amazing, that works now. Thank you!