如何创建键为FString、值为泛型指针的UE TMap?
实现方案
UE 中 TMap 的值类型必须在编译期确定,你期望的直接用模板声明动态泛型值的写法无法实现「同时存储三种不同类型类指针」的需求,以下是两种可落地的实现方式:
方案1:公共基类继承(最推荐,符合UE开发规范)
这是UE生态下最常用的实现方式,类型安全且方便扩展:
- 先定义所有元素类的公共基类,可把公共方法声明为虚函数:
// 公共基类示例,如不需要UE反射也可改为普通C++类 UCLASS(Abstract) class YOUR_PROJECT_API UElementBase : public UObject { GENERATED_BODY() public: // 三个类共有的方法声明为虚函数,后续调用无需转型 virtual void TickElement(float DeltaTime) {}; };
- 让Earth、Wind、Fire三个自定义类都继承该基类,实现各自的逻辑:
UCLASS() class YOUR_PROJECT_API UEarth : public UElementBase { GENERATED_BODY() public: virtual void TickElement(float DeltaTime) override { // Earth类独有的实现逻辑 } // Earth类独有的方法 void EarthSpecialAction(); }; // Wind、Fire类同理继承UElementBase即可
- TMap定义与使用:
// TMap声明 TMap<FString, UElementBase*> ElementMap; // 写入数据示例(如果是Actor类请用SpawnActor创建实例) UEarth* EarthIns = NewObject<UEarth>(); ElementMap.Add(TEXT("Earth"), EarthIns); ElementMap.Add(TEXT("Wind"), NewObject<UWind>()); ElementMap.Add(TEXT("Fire"), NewObject<UFire>()); // 读取调用公共方法 if (UElementBase** FoundElement = ElementMap.Find(TEXT("Earth"))) { (*FoundElement)->TickElement(0.1f); // 自动调用UEarth的实现 } // 读取调用子类独有方法,用UE内置Cast安全转型 if (UElementBase** FoundElement = ElementMap.Find(TEXT("Earth"))) { if (UEarth* EarthIns = Cast<UEarth>(*FoundElement)) { EarthIns->EarthSpecialAction(); } }
方案2:TVariant存储多类型指针(无需公共基类)
如果你不想引入公共基类,且确定后续不会新增其他元素类型,可以用UE的TVariant容器存储固定的几种指针类型:
// 先定义支持三种指针的Variant类型 using FElementPtr = TVariant<UEarth*, UWind*, UFire*>; // TMap声明 TMap<FString, FElementPtr> ElementMap; // 写入数据 ElementMap.Add(TEXT("Earth"), FElementPtr(NewObject<UEarth>())); // 读取调用 if (FElementPtr* FoundPtr = ElementMap.Find(TEXT("Earth"))) { // 判断当前存储的是不是UEarth类型指针 if (UEarth** EarthIns = FoundPtr->GetIf<UEarth*>()) { (*EarthIns)->EarthSpecialAction(); } }
内容的提问来源于stack exchange,提问作者gcunrealdev
相关产品推荐
相关产品推荐

