[UnrealEngine4][C++] GENERATED_BODY() vs GENERATED_UCLASS_BODY()

posted in: UnrealEngine | 0

本篇文章使用引擎版本:4.11

在剛開始寫C++專案的時候肯定是被這二個macro搞的有點混亂,稍微有經驗一點的程式設計師馬上就會知道這二個macro肯定是用來產生某些預設方法用的。 其產生的檔案會放在YouProject\Intermediate\Build\Win64\UE4\Inc\YouProject\xxx.generated.h裡面。

然而在使用的過程當然,總是會看到一些範例程式一下子用GENERATED_BODY(),又一下子用GENERATED_UCLASS_BODY(),實在搞得我好混亂阿,到底要用那個才對?先說結論,GENERATED_UCLASS_BODY()其實是4.6版本之前留下來的macro,在4.6的時候其release note有以下說明:

  • You now define and use “normal” C++ constructors for your classes. You can use parameterless constructors too now!
  • You no longer need to supply a category for your properties to expose them to the editor or Blueprints. You’ll get a default category now.
  • FPostContructInitializeProperties is deprecated. It’s replaced by FObjectInitializer, and you only have to specify it when you actually need it.
  • “GENERATED_BODY” no longer resets your protection level to “public”. It will preserve your settings.
  • Please use the new “GENERATED_BODY” specifier instead of “GENERATED_UCLASS_BODY”. It enables many of these new improvements!

也就是說,4.6以上的版本都用GENERATED_BODY就行了,其主要的差異點在於你不需要再在cpp強逼去實作下面這個function。

UMyClass::UMyClass(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer){

}

取而代之的是,若你需要constructor,你只需要在.h宣告:

UMyClass();

之後在cpp實作就行了:

UMyClass::UMyClass(){ }

省掉那惱人對user而言完全不需要知道在幹嘛的FObjectInitializer,取而代之的是是更直覺的C++宣告,實在是乾淨許多。

另外補充一個不知道算不算bug的東西。

由於我需要在物件的destructor中做一些東西,根據Rule of Five 的指導,我必須同時宣告下面這五個function才行

virtual ~UMyClass() {  

//my implement

};
UMyClass(const UMyClass&) = default;

UMyClass& operator=(const UMyClass&) = default;
UMyClass(UMyClass&&) = default;
UMyClass& operator=(UMyClass&&) = default;

在宣告之後編輯發現編輯器說已經有宣告body了,本來有點感心說果然是UE4,居然連這個點都有handle到了。然而在追了一下原碼之後發現,卻引擎只有自動產生copy-constructor跟copy-assignment而已,move相關的都沒有實作到。

其中copy-constructor位置在MyClass.generated.h中的ENHANCED_CONSTRUCTORS下面:

private: \
    /** Private copy-constructor, should never be used */ \
    NO_API UMyClass(const UMyClass& InCopy); \

 

而Copy assignment則是在引擎中的ObjectBase.h下面的DECLARE_CLASS這個macro中宣告:

#define DECLARE_CLASS( TClass, TSuperClass, TStaticFlags, TStaticCastFlags, TPackage, TRequiredAPI  ) \
private: \
    TClass & operator=(TClass const &);   \  …

因此最後就只能自己再做個macro去補上對應的程式碼了。

雖然沒有嚴格遵守這個規則好像也不會怎麼樣……

Leave a Reply

Your email address will not be published. Required fields are marked *