Understanding ConstrustorStatics syntax

Hey guys, so I’ve been using C# for many years and just recently started to program in C++ for UE4. While I can see a lot of similarities I noticed that sometimes c++ just goes wild with their syntax. And thus I have a very hard time understand what is being called on what and how in the ConstructorStatics example:

ATimelineTestActor::ATimelineTestActor(const class FPostConstructInitializeProperties& PCIP)
        : Super(PCIP)
    {
        // Structure to hold one-time initialization
        struct FConstructorStatics
        {
            ConstructorHelpers::FObjectFinder Object0;
            FConstructorStatics()
                : Object0(TEXT("StaticMesh'/Game/UT3/Pickups/Pickups/Health_Large/Mesh/S_Pickups_Base_Health_Large.S_Pickups_Base_Health_Large'"))
            {
            }
        };
        static FConstructorStatics ConstructorStatics;
    
        // Property initialization
    
        StaticMesh = ConstructorStatics.Object0.Object;
    }

So in the constructor of this class, you define a new struct called FConstructorStatics? What is the following syntax, I have no idea where a call starts and ends:

            FConstructorStatics()
                : Object0(TEXT("StaticMesh'/Game/UT3/Pickups/Pickups/Health_Large/Mesh/S_Pickups_Base_Health_Large.S_Pickups_Base_Health_Large'"))
            {
            }

Sorry if this sounds noobish.

Hi Osman,

That is the initialiser list for the FConstructorStatics struct. C# has similar syntax for passing arguments to the base:

struct FConstructorStatics
{
    public FConstructorStatics()
        : base(...args...)
    {
    }
}

This is the syntax used to pass arguments to the base class in C#. C++ also allows you to pass arguments to the base class(es) in the same way, but you write the type name instead of ‘base’. You can’t just write ‘base’ because C++ allows multiple inheritance. However, UE also defines a Super typedef (alias) for UClasses which you can use in the same way, because the UClass programming model doesn’t allow for multiple inheritance.

However, in addition to bases, C++ allows you to pass arguments to data members (fields) in exactly the same way, by naming the member to be initialised. So that code there is constructing the Object0 member with that text string. The equivalent in C# would be:

struct FConstructorStatics
{
    ConstructorHelpers.FObjectFinder Object0;

    FConstructorStatics()
    {
        Object0 = new ConstructorHelpers.FObjectFinder("StaticMesh'/Game/UT3/Pickups/Pickups/Health_Large/Mesh/S_Pickups_Base_Health_Large.S_Pickups_Base_Health_Large'");
    }
}

In C++, that style of code can be bad/illegal for several reasons:

  • Structs (or classes - they are equivalent in C++ except for the default access of bases/members) can have a user-defined default constructor (which is exactly what FConstructorStatics is doing), and so default constructing Object0 immediately followed by the assignment of a different state can have a performance impact.
  • A struct/class may also have no default constructor, so you cannot default initialise it then assign.
  • C++ doesn’t have the equivalent of readonly, just const, and so const data members can only be initialised in the initialiser list.

Hope this helps,

Steve

Ah that is a lot more clear when it’s laid out like that. The huge string for the path didn’t help in the example, I’ll give this a go in a minute.

C++ intimidated me really quickly but with explanation like this I’m feeling much more comfortable, thanks a lot :slight_smile:

Steve explains the details below,

I think you might prefer this syntax personally as an actual implementation for your own use

static ConstructorHelpers::FObjectFinder SkeletalMeshOb(TEXT("SkeletalMesh'/Game/Character/RoyalSwordSkelMesh.RoyalSwordSkelMesh'"));
	RoyalSwordAsset = SkeletalMeshOb.Object;

Try using this syntax instead :slight_smile:

as follows

static ConstructorHelpers::FObjectFinder StaticMeshOb(TEXT("StaticMesh'/Game/UT3/Pickups/Pickups/Health_Large/Mesh/S_Pickups_Base_Health_Large.S_Pickups_Base_Health_Large'"));

	PickupAsset = StaticMeshOb.Object;

#.h

in your .h

UStaticMesh* PickupAsset;

#Simplified

  static ConstructorHelpers::FObjectFinder StaticMeshOb(TEXT(TheObjectPath));

    	PickupAsset = StaticMeshOb.Object;

TheObjectPath = "StaticMesh'/Game/UT3/Pickups/Pickups/Health_Large/Mesh/S_Pickups_Base_Health_Large.S_Pickups_Base_Health_Large'"

you can get this path for your own assets by right clicking on an asset and selecting "Copy Reference"
:slight_smile:

That does look a lot cleaner, thank you for your help.