Suppose you have a class with a method that you would like to be able to call from anywhere:
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
below. 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:
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 spiffy!" ) );
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!" ) );