Mix of both abstract and implemented functions in class

Hello,

is it possible in Unreal to create a C++ class that is abstract and has pure virtual (abstract) functions as well as member variables and fully implemented functions?

First I tried to create a standard class derived from UObject that has a pure virtual function something like this: virtual void MyFunction() = 0; but this results in the error cannot instantiate abstract class even though I do not instantiate it and I even put Abstract and NotBlueprintable in the UCLASS declaration. The error is generated from the GENERATED_BODY() macro.

Then I tried creating a UInterface, however this does not seem to allow implementing functions because if I extend my Interface in a child class, I receive an error like this:
Missing UFunction implementation of function 'MyFunction' from interface 'MyInterface'. This function needs a UFUNCTION() declaration. Even though it has a UFUNCTION declaration in the interface. I understand that interfaces as a concept are not meant to have implementations, but wanted to check if it would technically solve my problem.

So is there any way to have a class / interface that comes with both pure virtual and implemented functions in Unreal?

Thanks in advance

It varies a bit.

UCLASS() derived types cannot have abstract/pure-virtual functions because the Class-Default Object (CDO) has to be instanced at runtime.

Unreal has a Macro you can use (PURE_VIRTUAL), but all it’s really doing is creating the implementation and adding a checkNoEntry() runtime assert. Personally I prefer to add that myself with a comment, since the macro makes things ugly.

As for UINTERFACE() - the I###-part of the interface can actually have pure-virtual and pre-implemented functions, but as with all things relating to reflected interfaces there are some obscure caveats:

  • Interfaces with pure virtuals cannot be implemented in Blueprints (but those functions can be marked BlueprintCallable).

  • Interfaces with Blueprint Event functions do not call the default interface implementation if they are implemented in a Blueprint class. This is a somewhat obscure and silent issue.

  • IIRC, BP event ###_Implementation()'s cannot be pure_virtual either.

2 Likes

I’d like to offer that wanting to mix pure virtuals with implemented functions, means you’re doing implementation-inheritance rather than interface-inheritance, which generally leads to less robust, harder to maintain code. Certainly harder-to-reason-about, because there’s no good way in the language to assert things like “should call the parent function” versus “should not call the parent function;” you have to defer that to runtime asserts. Runtime asserts are way too late to get told you did something wrong.

This is an opinion, but it’s one based on long experience: Do not mix pure virtuals, and implemented member functions. Use one or the other. Pure virtual means “this is an interface,” and implemented-functions means “this is an implementation,” and not mixing them keeps code easier to work with over time.

3 Likes

Thanks both of you. The checkNoEntry() way should be good enough for me, so I would just sort of fake it.

@jwatte just to clarify: Implementation Inheritance just means that I extend a base class, and some of the functions may or may not be overriden, no? That just sounds like standard inheritance. Other than that I agree that generally speaking an interface should not come with an implementation. Thats why in other programming languages it’s actually not possible to add an implementation in interfaces.

Exactly – C#, Java, Go, and many other languages don’t support mixing interface and implementation, and C++ code will generally be easier to work with and less fragile if you choose to follow that same rule (even though the compiler doesn’t make you.)

1 Like