How to override struct functions?

I’m trying to make an abstract class of which I can easily make many different instances.
Usually I would use interfaces or abstract classes for this, but this is a hassle in C++ with all those seperate cpp and header files.
I’ve tried the following:



USTRUCT(BlueprintType)
struct FMapping{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PID)
		float Scalar;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PID)
		float ParamX;

	FMapping() {

	}

	virtual float Map(float x) {
		return x;
	}

	virtual FString ToString() {
		return "FMapping::ToString()";
	}
};

USTRUCT(BlueprintType)
struct FExponentialMapping : public FMapping {
	GENERATED_USTRUCT_BODY()

	FExponentialMapping() {
		Scalar = 200.0f;
		ParamX = 0.01f;
	}

	virtual float Map(float x) OVERRIDE {
		return Scalar * (1.0f - (1.0f / FMath::Exp(x * ParamX)));
	}
	
	/*Return Scalar * (1 - (1 / e^(x*ParamX)))*/
	virtual FString ToString() OVERRIDE {
		return FString::SanitizeFloat(Scalar) + " * (1 - (1 / e^(x*" + FString::SanitizeFloat(ParamX) + ")))";
	}
};


And I have this Blueprint callable function in my class:



FString AXSpherion::MappingToString(FMapping mapping) {
	return mapping.ToString();
}


Now whenever I call this function the result is always “FMapping::ToString()”, whereas if I call the ToString method on a FExponentialMapping instance I will get the overrided result.
What am I doing wrong here? I want the MappingToString function to also return the correctly overrided result.

You’re passing the struct by value. In C++ when you pass a struct subclass by value, it basically cuts out any property fields from the subclass and you end up with a version of the base class with the data of the passed in version. If you pass it by reference or pointer you’ll have better luck.

Thanks for the explanation, Marc. This works if I solely use C++. Unfortunately I made the MappingToString function so that I can use it in Blueprint, because I can’t declare UFUNCTION in structs.
It seems that it is not allowed to declare a UFUNCTION with a pointer to a struct and when I pass it by reference the argument only shows up as output parameter in Blueprint :frowning:
Is that a bug?

I see there should be a possibility to declare a parameter as ‘out’, but I don’t know what the correct syntax is for this. UFunctions | Unreal Engine Documentation
My current declaration is like this:



UFUNCTION(BlueprintCallable, Category = Utility)
		static FString MappingToString(FMapping& theMapping);


Passing the variable as reference is what flags it as out. If you passed it as const reference it would be an input. However, that won’t help you in this case because the way that we pass variables between C++ and the blueprint VM will involve a copy anyways even if it is a reference.

In general struct polymorphism is not really something that blueprint virtual machine supports. You might be able to cobble something together with some virtual machine magic, looking at SetStructurePropertyByName might give you some hints, but it will be a bit tricky if at all possible and certainly not the standard kind of function implementation (meaning far more susceptible to engine changes).

OK, thanks Marc. I’ve just worked around it for now.

For anyone who is still coming up to this post →
Add the macro UPARAM if you wan’t to have a input ref

MappingToString

From:
UFUNCTION(BlueprintCallable, Category = Utility)
static FString MappingToString(FMapping& theMapping);

To:
UFUNCTION(BlueprintCallable, Category = Utility)
static UPARAM(DisplayName=“StringMapping”)FString MappingToString(UPARAM(ref) FMapping& StructMapping);

1 Like