(function(){})()

(function(){})()

1.是什么?

答:定义了一匿名函数 并且执行!

2.为啥要怎么写?

比如:

写法一:

<head>

<script>

(function(){

     var xxx;

     function  OMG(){}

})()

</script>

</head>

<body

写法二:


<head>

<script>

     var xxx;

     function  OMG(){}

</script>

</head>

写法一 在闭包中 执行后变量会释放空间

写法二 变量仍会在整个页面


<think>我们正在讨论的是虚幻引擎中的TFunction。根据引用[1],TFunction的实现位于UnrealEngine/Engine/Source/Runtime/Core/Public/Templates/Function.h中。TFunction是UE中用于封装可调用对象的模板类,类似于C++11中的std::function。它可以存储函数指针、lambda表达式、成员函数指针等。 在虚幻引擎中使用TFunction的步骤: 1. 包含头文件:需要包含Function.h,但通常我们包含CoreMinimal.h即可,因为它会包含核心模板。 2. 声明TFunction类型:TFunction<返回类型(参数列表)>。例如:TFunction<void(int)>表示一个接受int参数且无返回值的函数。 3. 绑定可调用对象:可以将lambda、静态函数、绑定成员函数等赋值给TFunction对象。 4. 调用:使用operator()来调用存储的函数。 注意:在UE中,TFunction是值类型,可以按值传递,但要注意其捕获的对象生命周期。如果捕获了UObject,需要确保不会在对象销毁后调用。 示例代码: 假设我们有一个类,想要使用TFunction: 在头文件中: ```cpp #include "CoreMinimal.h" class MyClass { public: // 声明一个TFunction成员变量 TFunction<void(int)> MyFunction; // 设置函数的方法 void SetFunction(TFunction<void(int)> InFunction); // 执行函数 void ExecuteFunction(int Value); }; ``` 在源文件中: ```cpp void MyClass::SetFunction(TFunction<void(int)> InFunction) { MyFunction = InFunction; } void MyClass::ExecuteFunction(int Value) { if (MyFunction) { MyFunction(Value); } } ``` 使用示例: 我们可以绑定一个lambda表达式: ```cpp MyClass MyObject; MyObject.SetFunction([](int Val) { UE_LOG(LogTemp, Log, TEXT("Value: %d"), Val); }); MyObject.ExecuteFunction(5); // 输出: Value: 5 ``` 也可以绑定一个静态函数: ```cpp static void StaticFunction(int Val) { UE_LOG(LogTemp, Log, TEXT("Static Function: %d"), Val); } MyObject.SetFunction(StaticFunction); MyObject.ExecuteFunction(10); ``` 对于成员函数,我们可以使用lambda捕获this,但要注意生命周期。或者使用TBaseDelegate等UE的委托系统,但TFunction本身不支持直接绑定成员函数,需要借助lambda或静态函数。 重要提示:TFunction在UE4中从某个版本开始引入(大约4.16之后),如果使用较早版本可能没有。另外,TFunction是移动友好的,但不支持复制(因为可能包含捕获的对象,而捕获的对象可能不可复制),所以赋值操作会转移所有权。 另外,在UE中还有其他的函数包装器,如TUniqueFunction(不可复制,只能移动)和TSharedFunction(基于共享指针的函数包装)。TFunction是可复制的,但要求其包装的可调用对象也是可复制的。如果包装了不可复制的对象(例如有unique_ptr捕获的lambda),则不能使用TFunction,而应使用TUniqueFunction。 根据引用[2],我们还可以将TFunction与蓝图调用结合,但TFunction本身是C++的,不能直接暴露给蓝图。蓝图暴露的函数需要使用UFUNCTION,并且参数和返回值必须是UProperty支持的。如果需要在蓝图中调用,可以考虑使用动态委托(如DECLARE_DYNAMIC_DELEGATE)或者将TFunction用于内部C++逻辑。 总结使用步骤: 1. 确定需要封装的可调用对象的签名。 2. 创建TFunction对象并用可调用对象初始化。 3. 在适当的时候调用TFunction。 注意:在异步操作中,如延迟回调,要确保TFunction被调用时,它所捕获的对象仍然有效。 下面是一个在游戏代码中使用TFunction的简单示例: ```cpp // 在某个Actor类中 void AMyActor::BeginPlay() { Super::BeginPlay(); // 创建一个TFunction,用于在定时器触发时调用 TFunction<void()> TimerFunction = [this]() { UE_LOG(LogTemp, Log, TEXT("Timer triggered!")); // 注意:这里捕获了this,所以必须确保在Actor销毁后不会调用此函数 }; // 设置一个定时器,在5秒后执行 GetWorld()->GetTimerManager().SetTimer(TimerHandle, [TimerFunction]() { TimerFunction(); }, 5.0f, false); } ``` 但是注意:上面的例子中,TimerFunction被值捕获到lambda中,而lambda又被传递给定时器。这样在5秒后,定时器会调用lambda,lambda再调用TimerFunction。但是,如果在这5秒内,这个Actor被销毁了,那么TimerFunction中捕获的this就变成了野指针。因此,我们需要使用弱引用或者取消定时器。 改进版:使用弱引用 ```cpp void AMyActor::BeginPlay() { Super::BeginPlay(); TWeakObjectPtr<AMyActor> WeakThis(this); TFunction<void()> TimerFunction = [WeakThis]() { if (WeakThis.IsValid()) { UE_LOG(LogTemp, Log, TEXT("Timer triggered!")); } }; GetWorld()->GetTimerManager().SetTimer(TimerHandle, [TimerFunction]() { TimerFunction(); }, 5.0f, false); } ``` 或者,更常见的是在Actor销毁时清除定时器(在EndPlay或析构中)。 综上所述,TFunction是UE中一个强大的工具,用于封装各种可调用对象,但使用时需注意生命周期和线程安全(TFunction本身不是线程安全的)。 最后,关于引用[2]中的内容,它展示了如何将函数暴露给蓝图(使用UFUNCTION和BlueprintCallable),但TFunction不能直接用于UFUNCTION的参数或返回值。所以,如果需要在蓝图中传递函数,应使用委托(如FOnMyEvent)而不是TFunction。 相关问题: 1. TFunction与std::function有什么区别? 2. 如何在TFunction中绑定成员函数? 3. TFunction在什么情况下会复制? 4. 如何安全地在异步回调中使用TFunction? 5. TFunction和UE的委托系统(Delegate)有何异同?</think>在虚幻引擎中正确使用 `TFunction` 需要理解其核心机制和适用场景。以下是关键使用指南: ### 1. `TFunction` 基础概念 `TFunction` 是虚幻引擎的泛型函数包装器(类似 C++11 的 `std::function`),用于封装任意可调用对象: ```cpp #include "Templates/Function.h" // 必需头文件 // 定义函数签名:返回类型(参数列表) TFunction<void(int, FString)> MyFunction; ``` ### 2. 绑定可调用对象的三种方式 #### (1) Lambda 表达式(最常用) ```cpp MyFunction = [](int Count, FString Name) { UE_LOG(LogTemp, Warning, TEXT("Count: %d, Name: %s"), Count, *Name); }; ``` #### (2) 静态函数 ```cpp static void StaticFunc(int Count, FString Name) { // 函数实现 } MyFunction = &StaticFunc; ``` #### (3) 成员函数(需结合 Lambda) ```cpp class MyClass { public: void MemberFunc(int Count, FString Name) { /*...*/ } }; MyClass Obj; MyFunction = [&Obj](int C, FString N) { Obj.MemberFunc(C, N); }; ``` ### 3. 调用与执行 ```cpp // 安全调用检查 if(MyFunction.IsBound()) { MyFunction.Execute(42, TEXT("Unreal")); // 显式调用 // 或直接 MyFunction(42, TEXT("Unreal")); } ``` ### 4. 结合蓝图暴露的实战示例(引用[2]扩展) ```cpp // MyActor.h #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MyActor.generated.h" UCLASS() class MYPROJECT_API AMyActor : public AActor { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category = "TFunction Demo") void RunTFunctionExample(); private: TFunction<void(FString)> BoundFunction; }; ``` ```cpp // MyActor.cpp void AMyActor::RunTFunctionExample() { // 绑定Lambda到TFunction BoundFunction = [](FString Message) { UE_LOG(LogTemp, Display, TEXT("Received: %s"), *Message); UKismetSystemLibrary::PrintString(this, Message, true, false); }; // 模拟事件触发 GetWorld()->GetTimerManager().SetTimerForNextTick([this]() { if(BoundFunction.IsBound()) { BoundFunction(TEXT("Hello from TFunction!")); } }); } ``` ### 5. 使用注意事项 1. **生命周期管理** - 避免捕获将被销毁的局部对象 - 对UObject使用弱引用: ```cpp TWeakObjectPtr<UMyObject> WeakObj = ...; BoundFunction = [WeakObj]() { if(WeakObj.IsValid()) WeakObj->Method(); }; ``` 2. **线程安全** - `TFunction` 非线程安全,跨线程调用需加锁 - 游戏线程中建议使用: ```cpp AsyncTask(ENamedThreads::GameThread, [MyFunction]() { MyFunction.ExecuteIfBound(); }); ``` 3. **性能优化** - 小规模调用:直接使用 Lambda - 高频调用:预绑定函数指针 - 避免在每帧中动态绑定 ### 6. 与蓝图交互的最佳实践 ```mermaid graph LR A[蓝图调用UFUNCTION] --> B[C++创建TFunction] B --> C[绑定Lambda/静态函数] C --> D[异步操作/定时器触发] D --> E[执行TFunction] E --> F[调用蓝图可访问的方法] ``` > 关键点:`TFunction` 本身不能直接暴露给蓝图,需通过UFUNCTION包装器桥接[^2] ### 常见问题解决方案 1. **绑定失败检查** ```cpp if(!MyFunction.IsBound()) { UE_LOG(LogTemp, Error, TEXT("Function not bound!")); return; } ``` 2. **参数传递错误** - 确保签名完全匹配 - 使用 `TFunction<void()>` 无参数版本简化调用 3. **多播支持** - 单播:`TFunction` - 多播:使用 `TArray<TFunction<...>>` 或 `DECLARE_MULTICAST_DELEGATE`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值