4.3 KiB
4.3 KiB
SealedEvent
-
功能描述: 无法在子类中覆盖此函数。SealedEvent关键词只能用于事件。对于非事件函数,请将它们声明为static或final,以密封它们。
-
元数据类型: bool
-
引擎模块: Behavior
-
作用机制: 在FunctionFlags中添加FUNC_Final
在源码里搜索:发现都是用在网络的函数上
UHT中的处理:
//先识别符号
[UhtSpecifier(Extends = UhtTableNames.Function, ValueType = UhtSpecifierValueType.Legacy)]
private static void SealedEventSpecifier(UhtSpecifierContext specifierContext)
{
UhtFunction function = (UhtFunction)specifierContext.Type;
function.FunctionExportFlags |= UhtFunctionExportFlags.SealedEvent;
}
//再设置标记
// Handle the initial implicit/explicit final
// A user can still specify an explicit final after the parameter list as well.
if (automaticallyFinal || function.FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent))
{
function.FunctionFlags |= EFunctionFlags.Final;
function.FunctionExportFlags |= UhtFunctionExportFlags.Final | UhtFunctionExportFlags.AutoFinal;
}
再验证:限定只能用在Event上。
if (FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent) && !FunctionFlags.HasAnyFlags(EFunctionFlags.Event))
{
this.LogError("SealedEvent may only be used on events");
}
if (FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent) && FunctionFlags.HasAnyFlags(EFunctionFlags.BlueprintEvent))
{
this.LogError("SealedEvent cannot be used on Blueprint events");
}
测试代码:
//Error: "SealedEvent may only be used on events"
UFUNCTION(SealedEvent)
void MyFunc_SealedEvent() {}
//Error: "SealedEvent cannot be used on Blueprint events"
UFUNCTION(BlueprintCallable,BlueprintImplementableEvent,SealedEvent)
void MyFunc_ImplementableEvent();
//Error: "SealedEvent cannot be used on Blueprint events"
UFUNCTION(BlueprintCallable,BlueprintNativeEvent,SealedEvent)
void MyFunc_NativeEvent();
因此无法用于普通的函数,又无法用于蓝图中的Event。所以既是Event又不是BlueprintEvent的是什么?看源码是只有网络的一些函数。
通过对比,发现Sealed函数的区别是多了FUNC_Final的标记。但FUNC_Final又不一定必须要以SealedEvent才能添加,exec或普通的BlueprintCallable函数都会添加。但是如果是vitural的函数就不会添加。在UHT中的原理是:
private static UhtParseResult ParseUFunction(UhtParsingScope parentScope, UhtToken token)
{
if (function.FunctionFlags.HasAnyFlags(EFunctionFlags.Net))
{
// Network replicated functions are always events, and are only final if sealed
scopeName = "event";
tokenContext.Reset(scopeName);
automaticallyFinal = false;
}
// If virtual, remove the implicit final, the user can still specifying an explicit final at the end of the declaration
if (function.FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.Virtual))
{
automaticallyFinal = false;
}
// Handle the initial implicit/explicit final
// A user can still specify an explicit final after the parameter list as well.
if (automaticallyFinal || function.FunctionExportFlags.HasAnyFlags(UhtFunctionExportFlags.SealedEvent))
{
function.FunctionFlags |= EFunctionFlags.Final;
function.FunctionExportFlags |= UhtFunctionExportFlags.Final | UhtFunctionExportFlags.AutoFinal;
}
}
在自己的C++代码中测试,发现在C++中怎么继承都不会触发编译错误。因此如果想拒绝被继承,还是用C++标准是final关键字。在函数末尾加final。
E:\P4V\Engine\Source\Editor\KismetCompiler\Private\KismetCompiler.cpp
const uint32 OverrideFlagsToCheck = (FUNC_FuncOverrideMatch & ~FUNC_AccessSpecifiers);
if ((Context.Function->FunctionFlags & OverrideFlagsToCheck) != (OverridenFunction->FunctionFlags & OverrideFlagsToCheck))
{
MessageLog.Error(*LOCTEXT("IncompatibleOverrideFlags_Error", "Overriden function is not compatible with the parent function @@. Check flags: Exec, Final, Static.").ToString(), Context.EntryPoint);
}
在编译的时候检测的是否是重载父类的函数,但因为SealedEvent不作用于普通函数,也不作用于BlueprintEvent,因此感觉只能在C++中继承。