Constructor with or without FObjectInitializer

I found this old post from version 4.6 where [MENTION=4893] [/MENTION] seems to indicate that this is the correct way to create a class constructor.


// MyActor.h

UCLASS()
class TESTCONSTRUCTOR_API AMyActor : public AActor
{
	GENERATED_BODY()
	
        // Constructor declaration
	AMyActor(const FObjectInitializer& ObjectInitializer);
};

/*********************************/

// MyActor.cpp

#include "MyActor.h"

AMyActor::AMyActor(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    // Class constructor/initialization code
}

Someone posts at the end of that thread about it no longer working in version 4.10 and [MENTION=14493]Doug Wilson[/MENTION] mentions about the engine changing since then.

Fast forward to today, when I create a new C++ class through the editor using version 4.13, I’m presented with something like this (paraphrased) in Visual Studio.


// MyActor.h

UCLASS()
class TESTCONSTRUCTOR_API AMyActor : public AActor
{
	GENERATED_BODY()
	
        // Constructor declaration
	AMyActor();
};

/*********************************/

// MyActor.cpp

#include "MyActor.h"

AMyActor::AMyActor()
{
    // Class constructor/initialization code
}

Notice there is no FObjectInitializer parameter and no call to the base constructor.

So can anyone clarify what is now the correct way?

Recent engine versions have been increasingly trying to look like “traditional” c++ if that’s even a thing. i guess a better way of putting it is older engines were more strict at how you typed code. like before you had to include that ObjIniti. Now you can choose to include it or not. basically follows the fundamental model of use what you need.

This is how i use it.


[TABLE]


class AMyActor : public AActor



{



    GENERATED_BODY()



public:



    AMyActor(const FObjectInitializer& ObjectInitializer);


}






[TABLE]

AMyActor::AMyActor(const FObjectInitializer& ObjectInitializer)


[TABLE]
[TR]
[TD] : Super(ObjectInitializer)


{

}


[/TD]
[/TR]



Hi wilberolive,

There have been several changes to how class constructors can be implemented in the Engine. In the current version of the Engine, you have three different options for how to declare your class constructor. The first two, in order of preferred use, are:



AMyActor();

AMyActor(const FObjectInitializer& ObjectInitializer);


Both of these will work the same. The third option is to not declare a constructor for your class. If you do not need to set anything up in the constructor, you can omit it entirely.

2 Likes

I still always use FObjectInitializer personally, ran into far too many problems not using it - especially on inherited classes.

4 Likes

This is because constructors do not have proper inheritance, a constructor of a derived class needs to perform more things than that of a base class has to. Which is the initialisation of its data members, which the base class cannot and will not know about.

Edit i should also say that destructors are the same as constructors, they are never inherited and therefore never overridden.

Here is an exercise

Can this code compile? Can it run ? What will it do if it can ?



class ABaseClass : public AActor
{
     GENERATED_BODY()
public:  
     AMyActor(const FObjectInitializer& ObjectInitializer);
}


ABaseClass::ABaseClass(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
     // Some use of ObjectInitializer

}


class ADerivedClass : public ABaseClass 
{
     GENERATED_BODY()
public:  
     ADerivedClass();
}


ADerivedClass::ADerivedClass()
{
     // What would happen here ?
}


…well I’m just getting back to C++ after years. Now I have to know the answer. Can you kindly brief me on this?

as long you dont have to replace any base component (such as replacing the MovementComponent class) that basic constructor works just fine if you don’t use the GENERATED_CLASS_BODY() macro. (using GENERATED_BODY() instead).

Good day!
So if I need to rewrite the logic of the “MovementComponent class” it is better to use this one?


AMyActor(const FObjectInitializer& ObjectInitializer);

and if I do not need to rewrite I can use this one?



AMyActor();

but as SaxonRah said it is not the best way… In my own exp. i remember that if I do not specify the parent class params in constructor with Super() it will use default constructor(w/o params)

and what do they do and what the diff besides allowing you to override some data? and if GENERATED_CLASS_BODY() is still relevant?
GENERATED_CLASS_BODY() macro vs using GENERATED_BODY() ?

and what if I have character with constructor like this:
AMyCharacter();
Is it a good way of doing it or could it be fraught?

Thank you!