A palavra-chave static em C++ pode ser usada com variáveis, funções e objetos. Neste artigo vamos focar no uso de static ao declarar funções em uma classe.
Quando uma função é declarada como static em uma classe C++, ela possui um escopo de classe. Isto significa que ela é independente das instâncias da classe e pode ser chamada usando apenas o nome da classe e o operador ::.
Consequentemente, uma função static não tem acesso as variáveis das instâncias. As únicas variáveis que ela consegue acessar, são as variáveis que também foram declaradas como static.
O código abaixo mostra um exemplo simples de uma função static que calcula o quadrado de um número.
static float Square(float value)
{
return value * value;
}
Você não precisa criar uma instância da classe para poder chamar a função static. Assumindo que a função foi criada em uma classe com o nome ATestStatic, a chamada da função Square() pode ser feita assim:
float result = ATestStatic::Square(4.5f);
A palavra-chave static é bastante usada na criação de funções utilitárias de gameplay. Um exemplo disso é a classe UGameplayStatics que contém diversas funções static que podem ser chamadas em C++ e em Blueprint.
A UGameplayStatics é uma Blueprint Function Library. Em outro artigo veremos como criar uma Blueprint Function Library.
O código abaixo mostra as declarações de cinco funções da classe UGameplayStatics que são frequentemente usadas.
UFUNCTION(BlueprintPure, Category="Game",
meta=(WorldContext="WorldContextObject",
UnsafeDuringActorConstruction="true"))
static class APawn* GetPlayerPawn(const UObject* WorldContextObject,
int32 PlayerIndex);
UFUNCTION(BlueprintPure, Category="Game",
meta=(WorldContext="WorldContextObject",
UnsafeDuringActorConstruction="true"))
static class APlayerController* GetPlayerController(
const UObject* WorldContextObject,
int32 PlayerIndex);
UFUNCTION(BlueprintCallable,
meta=(WorldContext="WorldContextObject",
AdvancedDisplay = "2",
DisplayName = "Open Level (by Name)"),
Category="Game")
static void OpenLevel(const UObject* WorldContextObject, FName LevelName,
bool bAbsolute = true, FString Options = FString(TEXT("")));
UFUNCTION(BlueprintCallable, Category="Audio",
meta=(WorldContext="WorldContextObject",
AdvancedDisplay = "3",
UnsafeDuringActorConstruction = "true",
Keywords = "play"))
static void PlaySoundAtLocation(const UObject* WorldContextObject,
USoundBase* Sound, FVector Location, FRotator Rotation,
float VolumeMultiplier = 1.f, float PitchMultiplier = 1.f,
float StartTime = 0.f,
class USoundAttenuation* AttenuationSettings = nullptr,
USoundConcurrency* ConcurrencySettings = nullptr,
AActor* OwningActor = nullptr);
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Game|Damage")
static float ApplyDamage(AActor* DamagedActor, float BaseDamage,
AController* EventInstigator, AActor* DamageCauser,
TSubclassOf<class UDamageType> DamageTypeClass);
As imagens abaixo mostram os nodes Blueprint equivalentes às funções acima.
Observe que algumas funções possuem como primeiro parâmetro um UObject* WorldContextObject e que este parâmetro não aparece nos nodes Blueprint. O WorldContextObject será o tópico do próximo artigo.