UE4函数标记BlueprintImplementableEvent和BlueprintNativeEvent区别

本文深入探讨了在Unreal Engine 4(UE4)中,如何使用BlueprintImplementableEvent和BlueprintNativeEvent实现蓝图与C++代码的交互。详细讲解了这两种修饰符的区别,包括函数声明、定义及调用方式,以及蓝图如何重写实现这些函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/// This function is designed to be overridden by a blueprint.  Do not provide a body for this function;
        /// the autogenerated code will include a thunk that calls ProcessEvent to execute the overridden body.
        BlueprintImplementableEvent,

        /// This function is designed to be overridden by a blueprint, but also has a native implementation.
        /// Provide a body named [FunctionName]_Implementation instead of [FunctionName]; the autogenerated
        /// code will include a thunk that calls the implementation method when necessary.
        BlueprintNativeEvent,
 

BlueprintImplementableEvent:在C++可以声明函数(不能定义,蓝图重写),在C++里调用该函数,蓝图重写实现该函数

BlueprintNativeEvent:在C++可以声明和定义函数,在C++里调用该函数,蓝图重写实现该函数(蓝图可以重写或不重写C++父类函数)

MyTPCharacter.h

函数声明(BlueprintImplementableEvent和BlueprintNativeEvent):


	UFUNCTION(BlueprintImplementableEvent)
		void TestA();

	UFUNCTION(BlueprintImplementableEvent)
		int TestB();

	UFUNCTION(BlueprintImplementableEvent)
		void TestC(const FString& str);

	UFUNCTION(BlueprintImplementableEvent)
		int TestD(const FString& str);

	UFUNCTION(BlueprintNativeEvent)
		void TestE();

	UFUNCTION(BlueprintNativeEvent)
		int TestF();

	UFUNCTION(BlueprintNativeEvent)
		void TestG(const FString& str);

	UFUNCTION(BlueprintNativeEvent)
		int TestH(const FString& str);

MyTPCharacter.cpp

函数定义(BlueprintImplementableEvent不能定义和BlueprintNativeEvent定义):

BlueprintNativeEvent修饰函数定义格式:函数名_Implementation

void AMyTPCharacter::TestE_Implementation()
{
	PrintScreenStr("TestE_Implementation");
}
int AMyTPCharacter::TestF_Implementation()
{
	PrintScreenStr("TestF_Implementation");
	return 1;

}
void AMyTPCharacter::TestG_Implementation(const FString& str)
{
	PrintScreenStr("TestG_Implementation " + str);
	
}
int AMyTPCharacter::TestH_Implementation(const FString& str)
{
	PrintScreenStr("TestH_Implementation " + str);
	return 1;
}

C++调用这些函数:

void AMyTPCharacter::OnRunEvent()
{

	 TestA();
	 TestB();
	 TestC("TestC");
	 TestD("TestC");
	 TestE();
	 TestF();
	 TestG("TestG");
	 TestH("TestH");

}

蓝图可以重写函数:如下图,选中重写实现

 

BlueprintImplementableEvent和BlueprintNativeEvent修饰函数,有返回值和没有返回值区别,如下

BlueprintImplementableEvent和BlueprintNativeEvent修饰函数,是否重写C++父类函数,如下

运行效果:

总结:BlueprintNativeEvent和BlueprintImplementableEvent修饰函数,如果没有函数返回值,那就是类似蓝图事件通知,如果有函数返回值,那就是类似蓝图函数重写;都可以传参和返回值;BlueprintNativeEvent修饰函数在C++有声明和定义实现,在蓝图可以覆写该函数,蓝图是否调用C++定义父类函数;BlueprintNativeEvent修饰函数只有声明,没有定义实现,只能在蓝图重写实现;BlueprintNativeEvent和BlueprintImplementableEvent修饰函数都只能在C++其他函数里调用。

<think>好的,用户问的是在UE C++里virtual虚函数是什么意思。先回顾一下之前的对话历史,用户之前让我用比喻的方式讲解了一些C++UE相关的概念,比如static、const、virtual/override、friend等,用户可能是个刚入门的小白,对编程术语不太熟悉,所以需要尽量用简单易懂的方式解释。 现在用户具体问到虚函数,我需要先确定用户是否已经理解之前的比喻,还是需要重新解释。之前用游乐园的父子设施来比喻virtualoverride,爸爸类定义基础规则,儿子类可以修改。可能需要再次用类似的比喻来巩固概念,同时结合UE C++的具体情况。 用户可能是在学习UE C++的过程中遇到了虚函数,想了解它的作用使用场景。需要解释清楚虚函数的基本概念,在继承多态中的作用,以及在UE中的具体应用,比如为什么UE推荐使用Override而不是Virtual,以及一些注意事项,比如虚函数在构造函数中的行为。 要注意使用之前的比喻,保持一致性,比如继续用游乐园的设施来举例,这样用户更容易联想。同时要提到UE的特有机制,比如UHT(Unreal Header Tool)宏(如UFUNCTION),这些可能在普通C++中不太一样的地方需要特别说明。 还要考虑用户可能的后续问题,比如虚函数纯虚函数区别,或者如何正确使用override关键字,所以解释时应该涵盖这些点,但不要过于深入,以免让用户感到困惑。最后用比喻总结,帮助用户记忆,确保内容结构清晰,分点说明,符合用户要求的逐步解决问题的方式。</think>好的!我用 **「游乐园设备升级」** 的比喻来解释,保证小白也能秒懂!🎢 --- ### **比喻设定** 把代码中的类(Class)想象成 **「游乐园的游乐设施」**: - **爸爸设施(基类)**:基础版过山车(比如只能直线行驶) - **儿子设施(派生类)**:升级版过山车(比如带旋转、喷火特效) - **`virtual`(虚函数)** ➜ 爸爸设施上贴了一个 **「允许儿子改装」** 的标签 - **`override`** ➜ 儿子设施说:「我要重新设计这个功能!」 --- ### **虚函数的本质** 在UE C++中,`virtual` 的作用是: **允许子类(儿子)改写父类(爸爸)的函数逻辑**,同时保留通过父类指针调用子类函数的能力(多态性)。 --- ### **具体场景演示** #### 1. **爸爸设施(基类)**:普通过山车 ```cpp // 爸爸过山车的类定义 class ABaseRollerCoaster : public AActor { public: // 虚函数:允许儿子改装 "启动" 逻辑 virtual void StartRide() { UE_LOG(LogTemp, Warning, TEXT("普通过山车:呜呜呜缓慢启动...")); } }; ``` #### 2. **儿子设施(派生类)**:炫酷过山车 ```cpp // 儿子过山车的类定义 class ACoolRollerCoaster : public ABaseRollerCoaster { public: // override表示要改写爸爸的StartRide virtual void StartRide() override { UE_LOG(LogTemp, Warning, TEXT("🔥 炫酷版:喷射火焰!360度旋转启动!")); } }; ``` #### 3. **实际使用效果** ```cpp // 假设有一个管理所有设施的控制器 ABaseRollerCoaster* SelectedRide = GetSelectedRide(); // 可能拿到爸爸或儿子的指针 SelectedRide->StartRide(); // 自动调用实际类型的版本! ``` - 如果拿到爸爸指针 ➜ 输出普通启动 - 如果拿到儿子指针 ➜ 输出炫酷特效启动 --- ### **为什么需要虚函数?** 1. **扩展性**:不改动原有代码,就能添加新功能(比如新增「水下过山车」) 2. **统一管理**:用父类指针操作所有子类对象(比如游乐园管理员一键启动所有过山车) 3. **强制规范**:父类定义必须存在的功能(比如所有设施必须有 `StartRide()`) --- ### **UE的特殊注意事项** 1. **优先用 `override` 关键字**:UE推荐明确标记重写(比普通C++更严格) 2. **虚函数与蓝图**: - 如果想在蓝图中重写C++虚函数,需添加 `BlueprintImplementableEvent` 或 `BlueprintNativeEvent` ```cpp // 允许蓝图继承者重写 UFUNCTION(BlueprintNativeEvent) void StartRide(); ``` 3. **构造函数中慎用虚函数**:此时子类尚未初始化,调用虚函数会执行父类版本! --- ### **比喻总结** 想象游乐园老板(父类)规定: - 所有过山车 **必须** 有「启动」功能(虚函数 = 必须遵守的规则) - 但允许分园长(子类)自己决定「怎么启动」(喷火/旋转/隐身 都可以) - 游客(外部代码)只需知道「按启动按钮」,具体效果由实际设施决定!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值