How to use interfaces in C++?

There are several ways to use an object as if it were of an interface type. What are the different implications of the following options? Are they all equivalent? Are some better than others?

// This class does not need to be modified.
UINTERFACE()
class ULauncher : public UInterface
{
	GENERATED_BODY()
};

class GAME_API ILauncher
{
	GENERATED_BODY()

public:
	UFUNCTION()
	virtual void Func() = 0;
...
}
  1. Try casting
if (ILauncher* Launcher = Cast<ILauncher>(SomeActor)){
	Launcher->Func();
}
  1. Use Implements function
if (SomeActor->Implements<ULauncher>()){
	Cast<ILauncher>(SomeActor)->Func();
}
  1. Use TScriptInterface
if (ILauncher* Launcher = TScriptInterface<ILauncher>(SomeActor).GetInterface()){
	Launcher->Func();
}

1 & 3 are equivalent. The problem with this option is that the cast returns nullptrif the interface has been implemented in blueprint. Not if the functions have been implemented in blueprint but if the class that extends the interface is a blueprint or not.

So you could derive an object from your interface with BlueprintImplementableEvents, make a blueprint of that C++ type and call the function with a cast to the interface type. But if you just create a blueprint and add it to the implement interface list, this cast will fail.

Option 2 is half right. The implements check will succeed for both cases. But when it succeeds, you need to do: ILauncher::Execute_Func(SomeActor);to actually call it (per the documentation here). Again, the cast will fail for blueprint implementations.

If you don’t want to deal with any of this, you can use NotBlueprintable or meta=(CannotImplementInterfaceInBlueprint)in the UINTERFACE macro. The meta used to be the way, but they added the NotBlueprintable option at somepoint. This will prevent the ability to select the interface in the implements interface list in blueprint so that you always need a C++ implementation first. This won’t stop you from adding BlueprintImpelmentable or BlueprintNative events if you still want to actually do the work in blueprint.

Interesting, thanks!

I don’t want to do anything with blueprints in this case. It’s all contained within the C++ portion.