Delegates

Data types that reference and execute member functions on C++ Objects

Choose your operating system:

Windows

macOS

Linux

Delegates can call member functions on C++ objects in a generic, type-safe way. A delegate can be bound dynamically to a member function of an arbitrary object, calling the function on the object at a future time, even if the caller does not know the object`s type. Delegates are safe to copy. You can also pass them by value, but this is not recommended because this process will allocate memory on the heap; whenever possible, pass delegates by reference. There are three types of delegates supported by the Engine:

Declaring Delegates

To declare a delegate, use one of the macros below; select the macro based on the signature of the function (or functions) that you intend to bind to the delegate. Each macro features parameters for the new delgate type name, as well as the function's return type (if not void ) and its parameters. Currently, delegate signatures support any combination of the following:

  • Functions returning a value

  • Functions declared as const

  • Up to four "payload" variables

  • Up to eight function parameters

Use this table to find the declaration macro to use to declare your delegate.

Function signature

Declaration macro

void Function()

DECLARE_DELEGATE(DelegateName)

void Function(Param1)

DECLARE_DELEGATE_OneParam(DelegateName, Param1Type)

void Function(Param1, Param2)

DECLARE_DELEGATE_TwoParams(DelegateName, Param1Type, Param2Type)

void Function(Param1, Param2, ...)

DECLARE_DELEGATE_<Num>Params(DelegateName, Param1Type, Param2Type, ...)

<RetValType> Function()

DECLARE_DELEGATE_RetVal(RetValType, DelegateName)

<RetValType> Function(Param1)

DECLARE_DELEGATE_RetVal_OneParam(RetValType, DelegateName, Param1Type)

<RetValType> Function(Param1, Param2)

DECLARE_DELEGATE_RetVal_TwoParams(RetValType, DelegateName, Param1Type, Param2Type)

<RetValType> Function(Param1, Param2, ...)

DECLARE_DELEGATE_RetVal_<Num>Params(RetValType, DelegateName, Param1Type, Param2Type, ...)

Delegate functions support the same Specifiers as UFunctions , but use the UDELEGATE macro instead of UFUNCTION . For example, the following code adds the BlueprintAuthorityOnly Specifier to the FInstigatedAnyDamageSignature delegate

UDELEGATE(BlueprintAuthorityOnly)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FInstigatedAnyDamageSignature, float, Damage, const UDamageType*, DamageType, AActor*, DamagedActor, AActor*, DamageCauser);

Variations of the macros above for multi-cast, dynamic, and wrapped delegates are as follows:

  • DECLARE_MULTICAST_DELEGATE...

  • DECLARE_DYNAMIC_DELEGATE...

  • DECLARE_DYNAMIC_MULTICAST_DELEGATE...

  • DECLARE_DYNAMIC_DELEGATE...

  • DECLARE_DYNAMIC_MULTICAST_DELEGATE...

Delegate signature declarations can exist at global scope, within a namespace, or even within a class declaration. These declarations may not exist within the body of a function.

See Dynamic Delegates and Multi-cast Delegates for more information on declaring these types of delegates.

Delegate functions support The same Specifiers as UFunctions , but use the UDELEGATE macro instead of UFUNCTION .

Binding Delegates

The delegate system understands certain types of objects, and additional features are enabled when using these objects. If you bind a delegate to a member of a UObject or shared pointer class, the delegate system can keep a weak reference to the object, so that if the object gets destroyed out from underneath the delegate, you will be able to handle these cases by calling IsBound or ExecuteIfBound functions. Note the special binding syntax for the various types of supported objects.

Function

Description

Bind

Binds to an existing delegate object.

BindStatic

Binds a raw C++ pointer global function delegate.

BindRaw

Binds a raw C++ pointer delegate. Since raw pointers do not use any sort of reference, calling Execute or ExecuteIfBound after deleting the target object is unsafe.

BindLambda

Binds a functor. This is generally used for lambda functions.

BindSP

Binds a shared pointer-based member function delegate. Shared pointer delegates keep a weak reference to your object. You can use ExecuteIfBound to call them.

BindUObject

Binds a UObject member function delegate. UObject delegates keep a weak reference to the UObject you target. You can use ExecuteIfBound to call them.

UnBind

Unbinds this delegate.

See DelegateSignatureImpl.inl (located in ..\UE4\Engine\Source\Runtime\Core\Public\Templates\ ) for the variations, arguments, and implementations of these functions.

Payload Data

When binding to a delegate, you can pass payload data along. These are arbitrary variables that will be passed directly to any bound function when it is invoked. This is really useful as it allows you to store parameters within the delegate itself at bind-time. All delegate types (except for "dynamic") supports payload variables automatically.
This example passes two custom variables, a bool and an int32 to a delegate. Then when the delegate is invoked, these parameters will be passed to your bound function. The extra variable arguments must always be accepted after the delegate type parameter arguments.

MyDelegate.BindRaw( &MyFunction, true, 20 );

Executing Delegates

The function bound to a delegate is executed by calling the delegate`s Execute() function. You must check if delegates are "bound" before executing them. This is to make the code more safe as there may be cases where delegates have return values and output parameters that are uninitialized and subsequently accessed. Executing an unbound delegate could actually scribble over memory in some instances. You can call IsBound() to check if the delegate is safe to execute. Also, for delegates that have no return value, you can call ExecuteIfBound() , but be wary of output parameters that may be left uninitialized.

Execution Functions

Description

Execute

Executes a delegate without checking its bindings

ExecuteIfBound

Checks that a delegate is bound, and if so, calls Execute

IsBound

Checks whether or not a delegate is bound, often before code that includes an Execute call

See Multi-cast Delegates for details on executing multi-cast delegates.

Example Usage

Suppose you have a class with a method that you would like to be able to call from anywhere:

class FLogWriter
{
    void WriteToLog(FString);
};

To call the WriteToLog function, we will need to create a delegate type for that function`s signature. To do this, you will first declare the delegate using one of the macros

  1. For example, here is a simple delegate type:

    DECLARE_DELEGATE_OneParam(FStringDelegate, FString);

This creates a delegate type called FStringDelegate that takes a single parameter of type FString .

Here is an example of how you would use this FStringDelegate in a class:

class FMyClass
{
    FStringDelegate WriteToLogDelegate;
};

This allows your class to hold a pointer to a method in an arbitrary class. The only thing the class really knows about this delegate is its function signature.

Now, to assign the delegate, simply create an instance of your delegate class, passing along the class that owns the method as a template parameter. You will also pass the instance of your object and the actual function address of the method. So, here we will create an instance of our FLogWriter class, then create a delegate for the WriteToLog method of that object instance:

TSharedRef<FLogWriter> LogWriter(new FLogWriter());

WriteToLogDelegate.BindSP(LogWriter, &FLogWriter::WriteToLog);

You have just dynamically bound a delegate to a method of a class! Pretty simple, right?

Note that the SP part of BindSP stands for shared pointer, because we are binding to an object that is owned by a shared pointer. There are versions for different object types, such as BindRaw() and BindUObject().

Now, your WriteToLog method can be called by FMyClass without it even knowing anything about the FLogWriter class! To call your delegate, just use the Execute() method:

WriteToLogDelegate.Execute(TEXT("Delegates are great!"));

If you call Execute() before binding a function to the delegate, an assertion will be triggered. In many cases, you will instead want to do this:

WriteToLogDelegate.ExecuteIfBound(TEXT("Only executes if a function was bound!"));
Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey
Dismiss